Commit e39f4ea9 authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab

edac: Only expose csrows/channels on legacy API if they're populated

This patch actually fixes a bug with the legacy API, where, at the
same csrow, some channels may have different DIMMs. This can happen
on FB-DIMM/RAMBUS and modern Intel controllers.

This is the case, for example, of Nehalem machines:

$ ./edac-ctl --layout
       +-----------------------------------+
       |                mc0                |
       | channel0  | channel1  | channel2  |
-------+-----------------------------------+
slot2: |     0 MB  |     0 MB  |     0 MB  |
slot1: |  1024 MB  |     0 MB  |     0 MB  |
slot0: |  1024 MB  |  1024 MB  |  1024 MB  |
-------+-----------------------------------+

Before this patch, non-filled memories were shown. Now, only what's
filled is there:

grep . /sys/devices/system/edac/mc/mc0/csrow*/ch?*
/sys/devices/system/edac/mc/mc0/csrow0/ch0_ce_count:0
/sys/devices/system/edac/mc/mc0/csrow0/ch0_dimm_label:CPU#0Channel#0_DIMM#0
/sys/devices/system/edac/mc/mc0/csrow0/ch1_ce_count:0
/sys/devices/system/edac/mc/mc0/csrow0/ch1_dimm_label:CPU#0Channel#0_DIMM#1
/sys/devices/system/edac/mc/mc0/csrow1/ch0_ce_count:0
/sys/devices/system/edac/mc/mc0/csrow1/ch0_dimm_label:CPU#0Channel#1_DIMM#0
/sys/devices/system/edac/mc/mc0/csrow2/ch0_ce_count:0
/sys/devices/system/edac/mc/mc0/csrow2/ch0_dimm_label:CPU#0Channel#2_DIMM#0

Thanks-to: Aristeu Rozanski Filho <arozansk@redhat.com>
Reviewed-by: default avatarAristeu Rozanski <arozansk@redhat.com>
Cc: Doug Thompson <norsk5@yahoo.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent fd63312d
...@@ -347,6 +347,16 @@ static struct device_attribute *dynamic_csrow_ce_count_attr[] = { ...@@ -347,6 +347,16 @@ static struct device_attribute *dynamic_csrow_ce_count_attr[] = {
&dev_attr_legacy_ch5_ce_count.attr &dev_attr_legacy_ch5_ce_count.attr
}; };
static inline int nr_pages_per_csrow(struct csrow_info *csrow)
{
int chan, nr_pages = 0;
for (chan = 0; chan < csrow->nr_channels; chan++)
nr_pages += csrow->channels[chan].dimm->nr_pages;
return nr_pages;
}
/* Create a CSROW object under specifed edac_mc_device */ /* Create a CSROW object under specifed edac_mc_device */
static int edac_create_csrow_object(struct mem_ctl_info *mci, static int edac_create_csrow_object(struct mem_ctl_info *mci,
struct csrow_info *csrow, int index) struct csrow_info *csrow, int index)
...@@ -371,6 +381,9 @@ static int edac_create_csrow_object(struct mem_ctl_info *mci, ...@@ -371,6 +381,9 @@ static int edac_create_csrow_object(struct mem_ctl_info *mci,
return err; return err;
for (chan = 0; chan < csrow->nr_channels; chan++) { for (chan = 0; chan < csrow->nr_channels; chan++) {
/* Only expose populated DIMMs */
if (!csrow->channels[chan].dimm->nr_pages)
continue;
err = device_create_file(&csrow->dev, err = device_create_file(&csrow->dev,
dynamic_csrow_dimm_attr[chan]); dynamic_csrow_dimm_attr[chan]);
if (err < 0) if (err < 0)
...@@ -405,6 +418,9 @@ static int edac_create_csrow_objects(struct mem_ctl_info *mci) ...@@ -405,6 +418,9 @@ static int edac_create_csrow_objects(struct mem_ctl_info *mci)
struct csrow_info *csrow; struct csrow_info *csrow;
for (i = 0; i < mci->nr_csrows; i++) { for (i = 0; i < mci->nr_csrows; i++) {
csrow = &mci->csrows[i];
if (!nr_pages_per_csrow(csrow))
continue;
err = edac_create_csrow_object(mci, &mci->csrows[i], i); err = edac_create_csrow_object(mci, &mci->csrows[i], i);
if (err < 0) if (err < 0)
goto error; goto error;
...@@ -414,7 +430,11 @@ static int edac_create_csrow_objects(struct mem_ctl_info *mci) ...@@ -414,7 +430,11 @@ static int edac_create_csrow_objects(struct mem_ctl_info *mci)
error: error:
for (--i; i >= 0; i--) { for (--i; i >= 0; i--) {
csrow = &mci->csrows[i]; csrow = &mci->csrows[i];
if (!nr_pages_per_csrow(csrow))
continue;
for (chan = csrow->nr_channels - 1; chan >= 0; chan--) { for (chan = csrow->nr_channels - 1; chan >= 0; chan--) {
if (!csrow->channels[chan].dimm->nr_pages)
continue;
device_remove_file(&csrow->dev, device_remove_file(&csrow->dev,
dynamic_csrow_dimm_attr[chan]); dynamic_csrow_dimm_attr[chan]);
device_remove_file(&csrow->dev, device_remove_file(&csrow->dev,
...@@ -433,7 +453,11 @@ static void edac_delete_csrow_objects(struct mem_ctl_info *mci) ...@@ -433,7 +453,11 @@ static void edac_delete_csrow_objects(struct mem_ctl_info *mci)
for (i = mci->nr_csrows - 1; i >= 0; i--) { for (i = mci->nr_csrows - 1; i >= 0; i--) {
csrow = &mci->csrows[i]; csrow = &mci->csrows[i];
if (!nr_pages_per_csrow(csrow))
continue;
for (chan = csrow->nr_channels - 1; chan >= 0; chan--) { for (chan = csrow->nr_channels - 1; chan >= 0; chan--) {
if (!csrow->channels[chan].dimm->nr_pages)
continue;
debugf1("Removing csrow %d channel %d sysfs nodes\n", debugf1("Removing csrow %d channel %d sysfs nodes\n",
i, chan); i, chan);
device_remove_file(&csrow->dev, device_remove_file(&csrow->dev,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment