aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/edac
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2012-03-29 11:20:22 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-06-11 12:23:44 -0400
commite39f4ea9b01f137f9e6fa631f3e9088fb9175e91 (patch)
tree3e334c0893f60a75b69355c631f52ed37fe028bd /drivers/edac
parentfd63312dfe70b8279618b4d77dc951b6e309ffa2 (diff)
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>
Diffstat (limited to 'drivers/edac')
-rw-r--r--drivers/edac/edac_mc_sysfs.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
index daa418b61525..0f671907c90b 100644
--- a/drivers/edac/edac_mc_sysfs.c
+++ b/drivers/edac/edac_mc_sysfs.c
@@ -347,6 +347,16 @@ static struct device_attribute *dynamic_csrow_ce_count_attr[] = {
347 &dev_attr_legacy_ch5_ce_count.attr 347 &dev_attr_legacy_ch5_ce_count.attr
348}; 348};
349 349
350static inline int nr_pages_per_csrow(struct csrow_info *csrow)
351{
352 int chan, nr_pages = 0;
353
354 for (chan = 0; chan < csrow->nr_channels; chan++)
355 nr_pages += csrow->channels[chan].dimm->nr_pages;
356
357 return nr_pages;
358}
359
350/* Create a CSROW object under specifed edac_mc_device */ 360/* Create a CSROW object under specifed edac_mc_device */
351static int edac_create_csrow_object(struct mem_ctl_info *mci, 361static int edac_create_csrow_object(struct mem_ctl_info *mci,
352 struct csrow_info *csrow, int index) 362 struct csrow_info *csrow, int index)
@@ -371,6 +381,9 @@ static int edac_create_csrow_object(struct mem_ctl_info *mci,
371 return err; 381 return err;
372 382
373 for (chan = 0; chan < csrow->nr_channels; chan++) { 383 for (chan = 0; chan < csrow->nr_channels; chan++) {
384 /* Only expose populated DIMMs */
385 if (!csrow->channels[chan].dimm->nr_pages)
386 continue;
374 err = device_create_file(&csrow->dev, 387 err = device_create_file(&csrow->dev,
375 dynamic_csrow_dimm_attr[chan]); 388 dynamic_csrow_dimm_attr[chan]);
376 if (err < 0) 389 if (err < 0)
@@ -405,6 +418,9 @@ static int edac_create_csrow_objects(struct mem_ctl_info *mci)
405 struct csrow_info *csrow; 418 struct csrow_info *csrow;
406 419
407 for (i = 0; i < mci->nr_csrows; i++) { 420 for (i = 0; i < mci->nr_csrows; i++) {
421 csrow = &mci->csrows[i];
422 if (!nr_pages_per_csrow(csrow))
423 continue;
408 err = edac_create_csrow_object(mci, &mci->csrows[i], i); 424 err = edac_create_csrow_object(mci, &mci->csrows[i], i);
409 if (err < 0) 425 if (err < 0)
410 goto error; 426 goto error;
@@ -414,7 +430,11 @@ static int edac_create_csrow_objects(struct mem_ctl_info *mci)
414error: 430error:
415 for (--i; i >= 0; i--) { 431 for (--i; i >= 0; i--) {
416 csrow = &mci->csrows[i]; 432 csrow = &mci->csrows[i];
433 if (!nr_pages_per_csrow(csrow))
434 continue;
417 for (chan = csrow->nr_channels - 1; chan >= 0; chan--) { 435 for (chan = csrow->nr_channels - 1; chan >= 0; chan--) {
436 if (!csrow->channels[chan].dimm->nr_pages)
437 continue;
418 device_remove_file(&csrow->dev, 438 device_remove_file(&csrow->dev,
419 dynamic_csrow_dimm_attr[chan]); 439 dynamic_csrow_dimm_attr[chan]);
420 device_remove_file(&csrow->dev, 440 device_remove_file(&csrow->dev,
@@ -433,7 +453,11 @@ static void edac_delete_csrow_objects(struct mem_ctl_info *mci)
433 453
434 for (i = mci->nr_csrows - 1; i >= 0; i--) { 454 for (i = mci->nr_csrows - 1; i >= 0; i--) {
435 csrow = &mci->csrows[i]; 455 csrow = &mci->csrows[i];
456 if (!nr_pages_per_csrow(csrow))
457 continue;
436 for (chan = csrow->nr_channels - 1; chan >= 0; chan--) { 458 for (chan = csrow->nr_channels - 1; chan >= 0; chan--) {
459 if (!csrow->channels[chan].dimm->nr_pages)
460 continue;
437 debugf1("Removing csrow %d channel %d sysfs nodes\n", 461 debugf1("Removing csrow %d channel %d sysfs nodes\n",
438 i, chan); 462 i, chan);
439 device_remove_file(&csrow->dev, 463 device_remove_file(&csrow->dev,