diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-03-29 11:20:22 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-06-11 12:23:44 -0400 |
commit | e39f4ea9b01f137f9e6fa631f3e9088fb9175e91 (patch) | |
tree | 3e334c0893f60a75b69355c631f52ed37fe028bd /drivers/edac | |
parent | fd63312dfe70b8279618b4d77dc951b6e309ffa2 (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.c | 24 |
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 | ||
350 | static 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 */ |
351 | static int edac_create_csrow_object(struct mem_ctl_info *mci, | 361 | static 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) | |||
414 | error: | 430 | error: |
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, |