diff options
-rw-r--r-- | drivers/edac/Kconfig | 8 | ||||
-rw-r--r-- | drivers/edac/edac_mc_sysfs.c | 165 |
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 | ||
32 | comment "Reporting subsystems" | 32 | comment "Reporting subsystems" |
33 | 33 | ||
34 | config 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 | |||
34 | config EDAC_DEBUG | 42 | config 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 */ | ||
456 | static 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 | |||
473 | static 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 | |||
485 | static 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 | |||
501 | static 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 | |||
509 | static 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 | |||
517 | static 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 | |||
525 | static 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 */ | ||
535 | static DEVICE_ATTR(dimm_label, S_IRUGO | S_IWUSR, | ||
536 | dimmdev_label_show, dimmdev_label_store); | ||
537 | static DEVICE_ATTR(dimm_location, S_IRUGO, dimmdev_location_show, NULL); | ||
538 | static DEVICE_ATTR(size, S_IRUGO, dimmdev_size_show, NULL); | ||
539 | static DEVICE_ATTR(dimm_mem_type, S_IRUGO, dimmdev_mem_type_show, NULL); | ||
540 | static DEVICE_ATTR(dimm_dev_type, S_IRUGO, dimmdev_dev_type_show, NULL); | ||
541 | static DEVICE_ATTR(dimm_edac_mode, S_IRUGO, dimmdev_edac_mode_show, NULL); | ||
542 | |||
543 | /* attributes of the dimm<id>/rank<id> object */ | ||
544 | static 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 | |||
554 | static struct attribute_group dimm_attr_grp = { | ||
555 | .attrs = dimm_attrs, | ||
556 | }; | ||
557 | |||
558 | static const struct attribute_group *dimm_attr_groups[] = { | ||
559 | &dimm_attr_grp, | ||
560 | NULL | ||
561 | }; | ||
562 | |||
563 | static void dimm_attr_release(struct device *device) | ||
564 | { | ||
565 | debugf1("Releasing dimm device %s\n", dev_name(device)); | ||
566 | } | ||
567 | |||
568 | static 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 */ | ||
574 | static 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]; |