mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-30 06:10:56 +00:00
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: Aristeu Rozanski <arozansk@redhat.com> Cc: Doug Thompson <norsk5@yahoo.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
fd63312dfe
commit
e39f4ea9b0
1 changed files with 24 additions and 0 deletions
|
@ -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,
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
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,
|
||||||
|
|
Loading…
Reference in a new issue