aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/edac/Kconfig8
-rw-r--r--drivers/edac/edac_mc_sysfs.c165
2 files changed, 172 insertions, 1 deletions
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index fdffa1beca17..3b3f84ff351f 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -31,6 +31,14 @@ if EDAC
31 31
32comment "Reporting subsystems" 32comment "Reporting subsystems"
33 33
34config EDAC_LEGACY_SYSFS
35 bool "EDAC legacy sysfs"
36 default y
37 help
38 Enable the compatibility sysfs nodes.
39 Use 'Y' if your edac utilities aren't ported to work with the newer
40 structures.
41
34config EDAC_DEBUG 42config EDAC_DEBUG
35 bool "Debugging" 43 bool "Debugging"
36 help 44 help
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
index 7002c9cab999..86da1767f86e 100644
--- a/drivers/edac/edac_mc_sysfs.c
+++ b/drivers/edac/edac_mc_sysfs.c
@@ -130,6 +130,7 @@ static const char *edac_caps[] = {
130 [EDAC_S16ECD16ED] = "S16ECD16ED" 130 [EDAC_S16ECD16ED] = "S16ECD16ED"
131}; 131};
132 132
133#ifdef CONFIG_EDAC_LEGACY_SYSFS
133/* 134/*
134 * EDAC sysfs CSROW data structures and methods 135 * EDAC sysfs CSROW data structures and methods
135 */ 136 */
@@ -443,6 +444,159 @@ static void edac_delete_csrow_objects(struct mem_ctl_info *mci)
443 device_del(&mci->csrows[i].dev); 444 device_del(&mci->csrows[i].dev);
444 } 445 }
445} 446}
447#endif
448
449/*
450 * Per-dimm (or per-rank) devices
451 */
452
453#define to_dimm(k) container_of(k, struct dimm_info, dev)
454
455/* show/store functions for DIMM Label attributes */
456static ssize_t dimmdev_location_show(struct device *dev,
457 struct device_attribute *mattr, char *data)
458{
459 struct dimm_info *dimm = to_dimm(dev);
460 struct mem_ctl_info *mci = dimm->mci;
461 int i;
462 char *p = data;
463
464 for (i = 0; i < mci->n_layers; i++) {
465 p += sprintf(p, "%s %d ",
466 edac_layer_name[mci->layers[i].type],
467 dimm->location[i]);
468 }
469
470 return p - data;
471}
472
473static ssize_t dimmdev_label_show(struct device *dev,
474 struct device_attribute *mattr, char *data)
475{
476 struct dimm_info *dimm = to_dimm(dev);
477
478 /* if field has not been initialized, there is nothing to send */
479 if (!dimm->label[0])
480 return 0;
481
482 return snprintf(data, EDAC_MC_LABEL_LEN, "%s\n", dimm->label);
483}
484
485static ssize_t dimmdev_label_store(struct device *dev,
486 struct device_attribute *mattr,
487 const char *data,
488 size_t count)
489{
490 struct dimm_info *dimm = to_dimm(dev);
491
492 ssize_t max_size = 0;
493
494 max_size = min((ssize_t) count, (ssize_t) EDAC_MC_LABEL_LEN - 1);
495 strncpy(dimm->label, data, max_size);
496 dimm->label[max_size] = '\0';
497
498 return max_size;
499}
500
501static ssize_t dimmdev_size_show(struct device *dev,
502 struct device_attribute *mattr, char *data)
503{
504 struct dimm_info *dimm = to_dimm(dev);
505
506 return sprintf(data, "%u\n", PAGES_TO_MiB(dimm->nr_pages));
507}
508
509static ssize_t dimmdev_mem_type_show(struct device *dev,
510 struct device_attribute *mattr, char *data)
511{
512 struct dimm_info *dimm = to_dimm(dev);
513
514 return sprintf(data, "%s\n", mem_types[dimm->mtype]);
515}
516
517static ssize_t dimmdev_dev_type_show(struct device *dev,
518 struct device_attribute *mattr, char *data)
519{
520 struct dimm_info *dimm = to_dimm(dev);
521
522 return sprintf(data, "%s\n", dev_types[dimm->dtype]);
523}
524
525static ssize_t dimmdev_edac_mode_show(struct device *dev,
526 struct device_attribute *mattr,
527 char *data)
528{
529 struct dimm_info *dimm = to_dimm(dev);
530
531 return sprintf(data, "%s\n", edac_caps[dimm->edac_mode]);
532}
533
534/* dimm/rank attribute files */
535static DEVICE_ATTR(dimm_label, S_IRUGO | S_IWUSR,
536 dimmdev_label_show, dimmdev_label_store);
537static DEVICE_ATTR(dimm_location, S_IRUGO, dimmdev_location_show, NULL);
538static DEVICE_ATTR(size, S_IRUGO, dimmdev_size_show, NULL);
539static DEVICE_ATTR(dimm_mem_type, S_IRUGO, dimmdev_mem_type_show, NULL);
540static DEVICE_ATTR(dimm_dev_type, S_IRUGO, dimmdev_dev_type_show, NULL);
541static DEVICE_ATTR(dimm_edac_mode, S_IRUGO, dimmdev_edac_mode_show, NULL);
542
543/* attributes of the dimm<id>/rank<id> object */
544static struct attribute *dimm_attrs[] = {
545 &dev_attr_dimm_label.attr,
546 &dev_attr_dimm_location.attr,
547 &dev_attr_size.attr,
548 &dev_attr_dimm_mem_type.attr,
549 &dev_attr_dimm_dev_type.attr,
550 &dev_attr_dimm_edac_mode.attr,
551 NULL,
552};
553
554static struct attribute_group dimm_attr_grp = {
555 .attrs = dimm_attrs,
556};
557
558static const struct attribute_group *dimm_attr_groups[] = {
559 &dimm_attr_grp,
560 NULL
561};
562
563static void dimm_attr_release(struct device *device)
564{
565 debugf1("Releasing dimm device %s\n", dev_name(device));
566}
567
568static struct device_type dimm_attr_type = {
569 .groups = dimm_attr_groups,
570 .release = dimm_attr_release,
571};
572
573/* Create a DIMM object under specifed memory controller device */
574static int edac_create_dimm_object(struct mem_ctl_info *mci,
575 struct dimm_info *dimm,
576 int index)
577{
578 int err;
579 dimm->mci = mci;
580
581 dimm->dev.type = &dimm_attr_type;
582 dimm->dev.bus = &mci->bus;
583 device_initialize(&dimm->dev);
584
585 dimm->dev.parent = &mci->dev;
586 if (mci->mem_is_per_rank)
587 dev_set_name(&dimm->dev, "rank%d", index);
588 else
589 dev_set_name(&dimm->dev, "dimm%d", index);
590 dev_set_drvdata(&dimm->dev, dimm);
591 pm_runtime_forbid(&mci->dev);
592
593 err = device_add(&dimm->dev);
594
595 debugf0("%s(): creating rank/dimm device %s\n", __func__,
596 dev_name(&dimm->dev));
597
598 return err;
599}
446 600
447/* 601/*
448 * Memory controller device 602 * Memory controller device
@@ -660,7 +814,6 @@ static struct device_type mci_attr_type = {
660 .release = mci_attr_release, 814 .release = mci_attr_release,
661}; 815};
662 816
663
664/* 817/*
665 * Create a new Memory Controller kobject instance, 818 * Create a new Memory Controller kobject instance,
666 * mc<id> under the 'mc' directory 819 * mc<id> under the 'mc' directory
@@ -725,11 +878,19 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
725 printk(KERN_CONT "\n"); 878 printk(KERN_CONT "\n");
726 } 879 }
727#endif 880#endif
881 err = edac_create_dimm_object(mci, dimm, i);
882 if (err) {
883 debugf1("%s() failure: create dimm %d obj\n",
884 __func__, i);
885 goto fail;
886 }
728 } 887 }
729 888
889#ifdef CONFIG_EDAC_LEGACY_SYSFS
730 err = edac_create_csrow_objects(mci); 890 err = edac_create_csrow_objects(mci);
731 if (err < 0) 891 if (err < 0)
732 goto fail; 892 goto fail;
893#endif
733 894
734 return 0; 895 return 0;
735 896
@@ -757,7 +918,9 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
757 918
758 debugf0("%s()\n", __func__); 919 debugf0("%s()\n", __func__);
759 920
921#ifdef CONFIG_EDAC_LEGACY_SYSFS
760 edac_delete_csrow_objects(mci); 922 edac_delete_csrow_objects(mci);
923#endif
761 924
762 for (i = 0; i < mci->tot_dimms; i++) { 925 for (i = 0; i < mci->tot_dimms; i++) {
763 struct dimm_info *dimm = &mci->dimms[i]; 926 struct dimm_info *dimm = &mci->dimms[i];