aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/edac/edac_mc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/edac/edac_mc.c')
-rw-r--r--drivers/edac/edac_mc.c687
1 files changed, 194 insertions, 493 deletions
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 3a7cfe88b169..4bde30bb3be7 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -1,6 +1,6 @@
1/* 1/*
2 * edac_mc kernel module 2 * edac_mc kernel module
3 * (C) 2005 Linux Networx (http://lnxi.com) 3 * (C) 2005, 2006 Linux Networx (http://lnxi.com)
4 * This file may be distributed under the terms of the 4 * This file may be distributed under the terms of the
5 * GNU General Public License. 5 * GNU General Public License.
6 * 6 *
@@ -33,13 +33,8 @@
33#include <asm/edac.h> 33#include <asm/edac.h>
34#include "edac_mc.h" 34#include "edac_mc.h"
35 35
36#define EDAC_MC_VERSION "Ver: 2.0.0 " __DATE__ 36#define EDAC_MC_VERSION "Ver: 2.0.1 " __DATE__
37 37
38/* For now, disable the EDAC sysfs code. The sysfs interface that EDAC
39 * presents to user space needs more thought, and is likely to change
40 * substantially.
41 */
42#define DISABLE_EDAC_SYSFS
43 38
44#ifdef CONFIG_EDAC_DEBUG 39#ifdef CONFIG_EDAC_DEBUG
45/* Values of 0 to 4 will generate output */ 40/* Values of 0 to 4 will generate output */
@@ -64,31 +59,12 @@ static int check_pci_parity = 0; /* default YES check PCI parity */
64static int panic_on_pci_parity; /* default no panic on PCI Parity */ 59static int panic_on_pci_parity; /* default no panic on PCI Parity */
65static atomic_t pci_parity_count = ATOMIC_INIT(0); 60static atomic_t pci_parity_count = ATOMIC_INIT(0);
66 61
67/* Structure of the whitelist and blacklist arrays */
68struct edac_pci_device_list {
69 unsigned int vendor; /* Vendor ID */
70 unsigned int device; /* Deviice ID */
71};
72
73#define MAX_LISTED_PCI_DEVICES 32
74
75/* List of PCI devices (vendor-id:device-id) that should be skipped */
76static struct edac_pci_device_list pci_blacklist[MAX_LISTED_PCI_DEVICES];
77static int pci_blacklist_count;
78
79/* List of PCI devices (vendor-id:device-id) that should be scanned */
80static struct edac_pci_device_list pci_whitelist[MAX_LISTED_PCI_DEVICES];
81static int pci_whitelist_count ;
82
83#ifndef DISABLE_EDAC_SYSFS
84static struct kobject edac_pci_kobj; /* /sys/devices/system/edac/pci */ 62static struct kobject edac_pci_kobj; /* /sys/devices/system/edac/pci */
85static struct completion edac_pci_kobj_complete; 63static struct completion edac_pci_kobj_complete;
86#endif /* DISABLE_EDAC_SYSFS */
87#endif /* CONFIG_PCI */ 64#endif /* CONFIG_PCI */
88 65
89/* START sysfs data and methods */ 66/* START sysfs data and methods */
90 67
91#ifndef DISABLE_EDAC_SYSFS
92 68
93static const char *mem_types[] = { 69static const char *mem_types[] = {
94 [MEM_EMPTY] = "Empty", 70 [MEM_EMPTY] = "Empty",
@@ -147,18 +123,10 @@ static struct completion edac_memctrl_kobj_complete;
147 * /sys/devices/system/edac/mc; 123 * /sys/devices/system/edac/mc;
148 * data structures and methods 124 * data structures and methods
149 */ 125 */
150#if 0
151static ssize_t memctrl_string_show(void *ptr, char *buffer)
152{
153 char *value = (char*) ptr;
154 return sprintf(buffer, "%s\n", value);
155}
156#endif
157
158static ssize_t memctrl_int_show(void *ptr, char *buffer) 126static ssize_t memctrl_int_show(void *ptr, char *buffer)
159{ 127{
160 int *value = (int*) ptr; 128 int *value = (int*) ptr;
161 return sprintf(buffer, "%d\n", *value); 129 return sprintf(buffer, "%u\n", *value);
162} 130}
163 131
164static ssize_t memctrl_int_store(void *ptr, const char *buffer, size_t count) 132static ssize_t memctrl_int_store(void *ptr, const char *buffer, size_t count)
@@ -224,11 +192,6 @@ struct memctrl_dev_attribute attr_##_name = { \
224 .store = _store, \ 192 .store = _store, \
225}; 193};
226 194
227/* cwrow<id> attribute f*/
228#if 0
229MEMCTRL_STRING_ATTR(mc_version,EDAC_MC_VERSION,S_IRUGO,memctrl_string_show,NULL);
230#endif
231
232/* csrow<id> control files */ 195/* csrow<id> control files */
233MEMCTRL_ATTR(panic_on_ue,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store); 196MEMCTRL_ATTR(panic_on_ue,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store);
234MEMCTRL_ATTR(log_ue,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store); 197MEMCTRL_ATTR(log_ue,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store);
@@ -257,8 +220,6 @@ static struct kobj_type ktype_memctrl = {
257 .default_attrs = (struct attribute **) memctrl_attr, 220 .default_attrs = (struct attribute **) memctrl_attr,
258}; 221};
259 222
260#endif /* DISABLE_EDAC_SYSFS */
261
262/* Initialize the main sysfs entries for edac: 223/* Initialize the main sysfs entries for edac:
263 * /sys/devices/system/edac 224 * /sys/devices/system/edac
264 * 225 *
@@ -268,11 +229,6 @@ static struct kobj_type ktype_memctrl = {
268 * !0 FAILURE 229 * !0 FAILURE
269 */ 230 */
270static int edac_sysfs_memctrl_setup(void) 231static int edac_sysfs_memctrl_setup(void)
271#ifdef DISABLE_EDAC_SYSFS
272{
273 return 0;
274}
275#else
276{ 232{
277 int err=0; 233 int err=0;
278 234
@@ -304,7 +260,6 @@ static int edac_sysfs_memctrl_setup(void)
304 260
305 return err; 261 return err;
306} 262}
307#endif /* DISABLE_EDAC_SYSFS */
308 263
309/* 264/*
310 * MC teardown: 265 * MC teardown:
@@ -312,7 +267,6 @@ static int edac_sysfs_memctrl_setup(void)
312 */ 267 */
313static void edac_sysfs_memctrl_teardown(void) 268static void edac_sysfs_memctrl_teardown(void)
314{ 269{
315#ifndef DISABLE_EDAC_SYSFS
316 debugf0("MC: " __FILE__ ": %s()\n", __func__); 270 debugf0("MC: " __FILE__ ": %s()\n", __func__);
317 271
318 /* Unregister the MC's kobject and wait for reference count to reach 272 /* Unregister the MC's kobject and wait for reference count to reach
@@ -324,144 +278,9 @@ static void edac_sysfs_memctrl_teardown(void)
324 278
325 /* Unregister the 'edac' object */ 279 /* Unregister the 'edac' object */
326 sysdev_class_unregister(&edac_class); 280 sysdev_class_unregister(&edac_class);
327#endif /* DISABLE_EDAC_SYSFS */
328} 281}
329 282
330#ifdef CONFIG_PCI 283#ifdef CONFIG_PCI
331
332#ifndef DISABLE_EDAC_SYSFS
333
334/*
335 * /sys/devices/system/edac/pci;
336 * data structures and methods
337 */
338
339struct list_control {
340 struct edac_pci_device_list *list;
341 int *count;
342};
343
344#if 0
345/* Output the list as: vendor_id:device:id<,vendor_id:device_id> */
346static ssize_t edac_pci_list_string_show(void *ptr, char *buffer)
347{
348 struct list_control *listctl;
349 struct edac_pci_device_list *list;
350 char *p = buffer;
351 int len=0;
352 int i;
353
354 listctl = ptr;
355 list = listctl->list;
356
357 for (i = 0; i < *(listctl->count); i++, list++ ) {
358 if (len > 0)
359 len += snprintf(p + len, (PAGE_SIZE-len), ",");
360
361 len += snprintf(p + len,
362 (PAGE_SIZE-len),
363 "%x:%x",
364 list->vendor,list->device);
365 }
366
367 len += snprintf(p + len,(PAGE_SIZE-len), "\n");
368 return (ssize_t) len;
369}
370
371/**
372 *
373 * Scan string from **s to **e looking for one 'vendor:device' tuple
374 * where each field is a hex value
375 *
376 * return 0 if an entry is NOT found
377 * return 1 if an entry is found
378 * fill in *vendor_id and *device_id with values found
379 *
380 * In both cases, make sure *s has been moved forward toward *e
381 */
382static int parse_one_device(const char **s,const char **e,
383 unsigned int *vendor_id, unsigned int *device_id)
384{
385 const char *runner, *p;
386
387 /* if null byte, we are done */
388 if (!**s) {
389 (*s)++; /* keep *s moving */
390 return 0;
391 }
392
393 /* skip over newlines & whitespace */
394 if ((**s == '\n') || isspace(**s)) {
395 (*s)++;
396 return 0;
397 }
398
399 if (!isxdigit(**s)) {
400 (*s)++;
401 return 0;
402 }
403
404 /* parse vendor_id */
405 runner = *s;
406
407 while (runner < *e) {
408 /* scan for vendor:device delimiter */
409 if (*runner == ':') {
410 *vendor_id = simple_strtol((char*) *s, (char**) &p, 16);
411 runner = p + 1;
412 break;
413 }
414
415 runner++;
416 }
417
418 if (!isxdigit(*runner)) {
419 *s = ++runner;
420 return 0;
421 }
422
423 /* parse device_id */
424 if (runner < *e) {
425 *device_id = simple_strtol((char*)runner, (char**)&p, 16);
426 runner = p;
427 }
428
429 *s = runner;
430 return 1;
431}
432
433static ssize_t edac_pci_list_string_store(void *ptr, const char *buffer,
434 size_t count)
435{
436 struct list_control *listctl;
437 struct edac_pci_device_list *list;
438 unsigned int vendor_id, device_id;
439 const char *s, *e;
440 int *index;
441
442 s = (char*)buffer;
443 e = s + count;
444 listctl = ptr;
445 list = listctl->list;
446 index = listctl->count;
447 *index = 0;
448
449 while (*index < MAX_LISTED_PCI_DEVICES) {
450 if (parse_one_device(&s,&e,&vendor_id,&device_id)) {
451 list[ *index ].vendor = vendor_id;
452 list[ *index ].device = device_id;
453 (*index)++;
454 }
455
456 /* check for all data consume */
457 if (s >= e)
458 break;
459 }
460
461 return count;
462}
463
464#endif
465static ssize_t edac_pci_int_show(void *ptr, char *buffer) 284static ssize_t edac_pci_int_show(void *ptr, char *buffer)
466{ 285{
467 int *value = ptr; 286 int *value = ptr;
@@ -529,31 +348,6 @@ struct edac_pci_dev_attribute edac_pci_attr_##_name = { \
529 .store = _store, \ 348 .store = _store, \
530}; 349};
531 350
532#if 0
533static struct list_control pci_whitelist_control = {
534 .list = pci_whitelist,
535 .count = &pci_whitelist_count
536};
537
538static struct list_control pci_blacklist_control = {
539 .list = pci_blacklist,
540 .count = &pci_blacklist_count
541};
542
543/* whitelist attribute */
544EDAC_PCI_STRING_ATTR(pci_parity_whitelist,
545 &pci_whitelist_control,
546 S_IRUGO|S_IWUSR,
547 edac_pci_list_string_show,
548 edac_pci_list_string_store);
549
550EDAC_PCI_STRING_ATTR(pci_parity_blacklist,
551 &pci_blacklist_control,
552 S_IRUGO|S_IWUSR,
553 edac_pci_list_string_show,
554 edac_pci_list_string_store);
555#endif
556
557/* PCI Parity control files */ 351/* PCI Parity control files */
558EDAC_PCI_ATTR(check_pci_parity, S_IRUGO|S_IWUSR, edac_pci_int_show, 352EDAC_PCI_ATTR(check_pci_parity, S_IRUGO|S_IWUSR, edac_pci_int_show,
559 edac_pci_int_store); 353 edac_pci_int_store);
@@ -582,18 +376,11 @@ static struct kobj_type ktype_edac_pci = {
582 .default_attrs = (struct attribute **) edac_pci_attr, 376 .default_attrs = (struct attribute **) edac_pci_attr,
583}; 377};
584 378
585#endif /* DISABLE_EDAC_SYSFS */
586
587/** 379/**
588 * edac_sysfs_pci_setup() 380 * edac_sysfs_pci_setup()
589 * 381 *
590 */ 382 */
591static int edac_sysfs_pci_setup(void) 383static int edac_sysfs_pci_setup(void)
592#ifdef DISABLE_EDAC_SYSFS
593{
594 return 0;
595}
596#else
597{ 384{
598 int err; 385 int err;
599 386
@@ -617,16 +404,13 @@ static int edac_sysfs_pci_setup(void)
617 404
618 return err; 405 return err;
619} 406}
620#endif /* DISABLE_EDAC_SYSFS */
621 407
622static void edac_sysfs_pci_teardown(void) 408static void edac_sysfs_pci_teardown(void)
623{ 409{
624#ifndef DISABLE_EDAC_SYSFS
625 debugf0("%s()\n", __func__); 410 debugf0("%s()\n", __func__);
626 init_completion(&edac_pci_kobj_complete); 411 init_completion(&edac_pci_kobj_complete);
627 kobject_unregister(&edac_pci_kobj); 412 kobject_unregister(&edac_pci_kobj);
628 wait_for_completion(&edac_pci_kobj_complete); 413 wait_for_completion(&edac_pci_kobj_complete);
629#endif
630} 414}
631 415
632 416
@@ -756,36 +540,6 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev)
756} 540}
757 541
758/* 542/*
759 * check_dev_on_list: Scan for a PCI device on a white/black list
760 * @list: an EDAC &edac_pci_device_list white/black list pointer
761 * @free_index: index of next free entry on the list
762 * @pci_dev: PCI Device pointer
763 *
764 * see if list contains the device.
765 *
766 * Returns: 0 not found
767 * 1 found on list
768 */
769static int check_dev_on_list(struct edac_pci_device_list *list,
770 int free_index, struct pci_dev *dev)
771{
772 int i;
773 int rc = 0; /* Assume not found */
774 unsigned short vendor=dev->vendor;
775 unsigned short device=dev->device;
776
777 /* Scan the list, looking for a vendor/device match */
778 for (i = 0; i < free_index; i++, list++ ) {
779 if ((list->vendor == vendor ) && (list->device == device )) {
780 rc = 1;
781 break;
782 }
783 }
784
785 return rc;
786}
787
788/*
789 * pci_dev parity list iterator 543 * pci_dev parity list iterator
790 * Scan the PCI device list for one iteration, looking for SERRORs 544 * Scan the PCI device list for one iteration, looking for SERRORs
791 * Master Parity ERRORS or Parity ERRORs on primary or secondary devices 545 * Master Parity ERRORS or Parity ERRORs on primary or secondary devices
@@ -799,22 +553,7 @@ static inline void edac_pci_dev_parity_iterator(pci_parity_check_fn_t fn)
799 * bumped until we are done with it 553 * bumped until we are done with it
800 */ 554 */
801 while((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { 555 while((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
802 /* if whitelist exists then it has priority, so only scan 556 fn(dev);
803 * those devices on the whitelist
804 */
805 if (pci_whitelist_count > 0 ) {
806 if (check_dev_on_list(pci_whitelist,
807 pci_whitelist_count, dev))
808 fn(dev);
809 } else {
810 /*
811 * if no whitelist, then check if this devices is
812 * blacklisted
813 */
814 if (!check_dev_on_list(pci_blacklist,
815 pci_blacklist_count, dev))
816 fn(dev);
817 }
818 } 557 }
819} 558}
820 559
@@ -855,154 +594,101 @@ static inline void clear_pci_parity_errors(void)
855 594
856#else /* CONFIG_PCI */ 595#else /* CONFIG_PCI */
857 596
858static inline void do_pci_parity_check(void) 597/* pre-process these away */
859{ 598#define do_pci_parity_check()
860 /* no-op */ 599#define clear_pci_parity_errors()
861} 600#define edac_sysfs_pci_teardown()
862 601#define edac_sysfs_pci_setup() (0)
863static inline void clear_pci_parity_errors(void)
864{
865 /* no-op */
866}
867
868static void edac_sysfs_pci_teardown(void)
869{
870}
871 602
872static int edac_sysfs_pci_setup(void)
873{
874 return 0;
875}
876#endif /* CONFIG_PCI */ 603#endif /* CONFIG_PCI */
877 604
878#ifndef DISABLE_EDAC_SYSFS 605/* EDAC sysfs CSROW data structures and methods
879 606 */
880/* EDAC sysfs CSROW data structures and methods */
881
882/* Set of more detailed csrow<id> attribute show/store functions */
883static ssize_t csrow_ch0_dimm_label_show(struct csrow_info *csrow, char *data)
884{
885 ssize_t size = 0;
886
887 if (csrow->nr_channels > 0) {
888 size = snprintf(data, EDAC_MC_LABEL_LEN,"%s\n",
889 csrow->channels[0].label);
890 }
891
892 return size;
893}
894 607
895static ssize_t csrow_ch1_dimm_label_show(struct csrow_info *csrow, char *data) 608/* Set of more default csrow<id> attribute show/store functions */
609static ssize_t csrow_ue_count_show(struct csrow_info *csrow, char *data, int private)
896{ 610{
897 ssize_t size = 0; 611 return sprintf(data,"%u\n", csrow->ue_count);
898
899 if (csrow->nr_channels > 0) {
900 size = snprintf(data, EDAC_MC_LABEL_LEN, "%s\n",
901 csrow->channels[1].label);
902 }
903
904 return size;
905} 612}
906 613
907static ssize_t csrow_ch0_dimm_label_store(struct csrow_info *csrow, 614static ssize_t csrow_ce_count_show(struct csrow_info *csrow, char *data, int private)
908 const char *data, size_t size)
909{ 615{
910 ssize_t max_size = 0; 616 return sprintf(data,"%u\n", csrow->ce_count);
911
912 if (csrow->nr_channels > 0) {
913 max_size = min((ssize_t)size,(ssize_t)EDAC_MC_LABEL_LEN-1);
914 strncpy(csrow->channels[0].label, data, max_size);
915 csrow->channels[0].label[max_size] = '\0';
916 }
917
918 return size;
919} 617}
920 618
921static ssize_t csrow_ch1_dimm_label_store(struct csrow_info *csrow, 619static ssize_t csrow_size_show(struct csrow_info *csrow, char *data, int private)
922 const char *data, size_t size)
923{ 620{
924 ssize_t max_size = 0; 621 return sprintf(data,"%u\n", PAGES_TO_MiB(csrow->nr_pages));
925
926 if (csrow->nr_channels > 1) {
927 max_size = min((ssize_t)size,(ssize_t)EDAC_MC_LABEL_LEN-1);
928 strncpy(csrow->channels[1].label, data, max_size);
929 csrow->channels[1].label[max_size] = '\0';
930 }
931
932 return max_size;
933} 622}
934 623
935static ssize_t csrow_ue_count_show(struct csrow_info *csrow, char *data) 624static ssize_t csrow_mem_type_show(struct csrow_info *csrow, char *data, int private)
936{ 625{
937 return sprintf(data,"%u\n", csrow->ue_count); 626 return sprintf(data,"%s\n", mem_types[csrow->mtype]);
938} 627}
939 628
940static ssize_t csrow_ce_count_show(struct csrow_info *csrow, char *data) 629static ssize_t csrow_dev_type_show(struct csrow_info *csrow, char *data, int private)
941{ 630{
942 return sprintf(data,"%u\n", csrow->ce_count); 631 return sprintf(data,"%s\n", dev_types[csrow->dtype]);
943} 632}
944 633
945static ssize_t csrow_ch0_ce_count_show(struct csrow_info *csrow, char *data) 634static ssize_t csrow_edac_mode_show(struct csrow_info *csrow, char *data, int private)
946{ 635{
947 ssize_t size = 0; 636 return sprintf(data,"%s\n", edac_caps[csrow->edac_mode]);
948
949 if (csrow->nr_channels > 0) {
950 size = sprintf(data,"%u\n", csrow->channels[0].ce_count);
951 }
952
953 return size;
954} 637}
955 638
956static ssize_t csrow_ch1_ce_count_show(struct csrow_info *csrow, char *data) 639/* show/store functions for DIMM Label attributes */
640static ssize_t channel_dimm_label_show(struct csrow_info *csrow,
641 char *data, int channel)
957{ 642{
958 ssize_t size = 0; 643 return snprintf(data, EDAC_MC_LABEL_LEN,"%s",
959 644 csrow->channels[channel].label);
960 if (csrow->nr_channels > 1) {
961 size = sprintf(data,"%u\n", csrow->channels[1].ce_count);
962 }
963
964 return size;
965} 645}
966 646
967static ssize_t csrow_size_show(struct csrow_info *csrow, char *data) 647static ssize_t channel_dimm_label_store(struct csrow_info *csrow,
648 const char *data,
649 size_t count,
650 int channel)
968{ 651{
969 return sprintf(data,"%u\n", PAGES_TO_MiB(csrow->nr_pages)); 652 ssize_t max_size = 0;
970}
971 653
972static ssize_t csrow_mem_type_show(struct csrow_info *csrow, char *data) 654 max_size = min((ssize_t)count,(ssize_t)EDAC_MC_LABEL_LEN-1);
973{ 655 strncpy(csrow->channels[channel].label, data, max_size);
974 return sprintf(data,"%s\n", mem_types[csrow->mtype]); 656 csrow->channels[channel].label[max_size] = '\0';
975}
976 657
977static ssize_t csrow_dev_type_show(struct csrow_info *csrow, char *data) 658 return max_size;
978{
979 return sprintf(data,"%s\n", dev_types[csrow->dtype]);
980} 659}
981 660
982static ssize_t csrow_edac_mode_show(struct csrow_info *csrow, char *data) 661/* show function for dynamic chX_ce_count attribute */
662static ssize_t channel_ce_count_show(struct csrow_info *csrow,
663 char *data,
664 int channel)
983{ 665{
984 return sprintf(data,"%s\n", edac_caps[csrow->edac_mode]); 666 return sprintf(data, "%u\n", csrow->channels[channel].ce_count);
985} 667}
986 668
669/* csrow specific attribute structure */
987struct csrowdev_attribute { 670struct csrowdev_attribute {
988 struct attribute attr; 671 struct attribute attr;
989 ssize_t (*show)(struct csrow_info *,char *); 672 ssize_t (*show)(struct csrow_info *,char *,int);
990 ssize_t (*store)(struct csrow_info *, const char *,size_t); 673 ssize_t (*store)(struct csrow_info *, const char *,size_t,int);
674 int private;
991}; 675};
992 676
993#define to_csrow(k) container_of(k, struct csrow_info, kobj) 677#define to_csrow(k) container_of(k, struct csrow_info, kobj)
994#define to_csrowdev_attr(a) container_of(a, struct csrowdev_attribute, attr) 678#define to_csrowdev_attr(a) container_of(a, struct csrowdev_attribute, attr)
995 679
996/* Set of show/store higher level functions for csrow objects */ 680/* Set of show/store higher level functions for default csrow attributes */
997static ssize_t csrowdev_show(struct kobject *kobj, struct attribute *attr, 681static ssize_t csrowdev_show(struct kobject *kobj,
998 char *buffer) 682 struct attribute *attr,
683 char *buffer)
999{ 684{
1000 struct csrow_info *csrow = to_csrow(kobj); 685 struct csrow_info *csrow = to_csrow(kobj);
1001 struct csrowdev_attribute *csrowdev_attr = to_csrowdev_attr(attr); 686 struct csrowdev_attribute *csrowdev_attr = to_csrowdev_attr(attr);
1002 687
1003 if (csrowdev_attr->show) 688 if (csrowdev_attr->show)
1004 return csrowdev_attr->show(csrow, buffer); 689 return csrowdev_attr->show(csrow,
1005 690 buffer,
691 csrowdev_attr->private);
1006 return -EIO; 692 return -EIO;
1007} 693}
1008 694
@@ -1013,8 +699,10 @@ static ssize_t csrowdev_store(struct kobject *kobj, struct attribute *attr,
1013 struct csrowdev_attribute * csrowdev_attr = to_csrowdev_attr(attr); 699 struct csrowdev_attribute * csrowdev_attr = to_csrowdev_attr(attr);
1014 700
1015 if (csrowdev_attr->store) 701 if (csrowdev_attr->store)
1016 return csrowdev_attr->store(csrow, buffer, count); 702 return csrowdev_attr->store(csrow,
1017 703 buffer,
704 count,
705 csrowdev_attr->private);
1018 return -EIO; 706 return -EIO;
1019} 707}
1020 708
@@ -1023,69 +711,157 @@ static struct sysfs_ops csrowfs_ops = {
1023 .store = csrowdev_store 711 .store = csrowdev_store
1024}; 712};
1025 713
1026#define CSROWDEV_ATTR(_name,_mode,_show,_store) \ 714#define CSROWDEV_ATTR(_name,_mode,_show,_store,_private) \
1027struct csrowdev_attribute attr_##_name = { \ 715struct csrowdev_attribute attr_##_name = { \
1028 .attr = {.name = __stringify(_name), .mode = _mode }, \ 716 .attr = {.name = __stringify(_name), .mode = _mode }, \
1029 .show = _show, \ 717 .show = _show, \
1030 .store = _store, \ 718 .store = _store, \
719 .private = _private, \
1031}; 720};
1032 721
1033/* cwrow<id>/attribute files */ 722/* default cwrow<id>/attribute files */
1034CSROWDEV_ATTR(size_mb,S_IRUGO,csrow_size_show,NULL); 723CSROWDEV_ATTR(size_mb,S_IRUGO,csrow_size_show,NULL,0);
1035CSROWDEV_ATTR(dev_type,S_IRUGO,csrow_dev_type_show,NULL); 724CSROWDEV_ATTR(dev_type,S_IRUGO,csrow_dev_type_show,NULL,0);
1036CSROWDEV_ATTR(mem_type,S_IRUGO,csrow_mem_type_show,NULL); 725CSROWDEV_ATTR(mem_type,S_IRUGO,csrow_mem_type_show,NULL,0);
1037CSROWDEV_ATTR(edac_mode,S_IRUGO,csrow_edac_mode_show,NULL); 726CSROWDEV_ATTR(edac_mode,S_IRUGO,csrow_edac_mode_show,NULL,0);
1038CSROWDEV_ATTR(ue_count,S_IRUGO,csrow_ue_count_show,NULL); 727CSROWDEV_ATTR(ue_count,S_IRUGO,csrow_ue_count_show,NULL,0);
1039CSROWDEV_ATTR(ce_count,S_IRUGO,csrow_ce_count_show,NULL); 728CSROWDEV_ATTR(ce_count,S_IRUGO,csrow_ce_count_show,NULL,0);
1040CSROWDEV_ATTR(ch0_ce_count,S_IRUGO,csrow_ch0_ce_count_show,NULL);
1041CSROWDEV_ATTR(ch1_ce_count,S_IRUGO,csrow_ch1_ce_count_show,NULL);
1042
1043/* control/attribute files */
1044CSROWDEV_ATTR(ch0_dimm_label,S_IRUGO|S_IWUSR,
1045 csrow_ch0_dimm_label_show,
1046 csrow_ch0_dimm_label_store);
1047CSROWDEV_ATTR(ch1_dimm_label,S_IRUGO|S_IWUSR,
1048 csrow_ch1_dimm_label_show,
1049 csrow_ch1_dimm_label_store);
1050 729
1051/* Attributes of the CSROW<id> object */ 730/* default attributes of the CSROW<id> object */
1052static struct csrowdev_attribute *csrow_attr[] = { 731static struct csrowdev_attribute *default_csrow_attr[] = {
1053 &attr_dev_type, 732 &attr_dev_type,
1054 &attr_mem_type, 733 &attr_mem_type,
1055 &attr_edac_mode, 734 &attr_edac_mode,
1056 &attr_size_mb, 735 &attr_size_mb,
1057 &attr_ue_count, 736 &attr_ue_count,
1058 &attr_ce_count, 737 &attr_ce_count,
1059 &attr_ch0_ce_count,
1060 &attr_ch1_ce_count,
1061 &attr_ch0_dimm_label,
1062 &attr_ch1_dimm_label,
1063 NULL, 738 NULL,
1064}; 739};
1065 740
1066/* No memory to release */ 741
742/* possible dynamic channel DIMM Label attribute files */
743CSROWDEV_ATTR(ch0_dimm_label,S_IRUGO|S_IWUSR,
744 channel_dimm_label_show,
745 channel_dimm_label_store,
746 0 );
747CSROWDEV_ATTR(ch1_dimm_label,S_IRUGO|S_IWUSR,
748 channel_dimm_label_show,
749 channel_dimm_label_store,
750 1 );
751CSROWDEV_ATTR(ch2_dimm_label,S_IRUGO|S_IWUSR,
752 channel_dimm_label_show,
753 channel_dimm_label_store,
754 2 );
755CSROWDEV_ATTR(ch3_dimm_label,S_IRUGO|S_IWUSR,
756 channel_dimm_label_show,
757 channel_dimm_label_store,
758 3 );
759CSROWDEV_ATTR(ch4_dimm_label,S_IRUGO|S_IWUSR,
760 channel_dimm_label_show,
761 channel_dimm_label_store,
762 4 );
763CSROWDEV_ATTR(ch5_dimm_label,S_IRUGO|S_IWUSR,
764 channel_dimm_label_show,
765 channel_dimm_label_store,
766 5 );
767
768/* Total possible dynamic DIMM Label attribute file table */
769static struct csrowdev_attribute *dynamic_csrow_dimm_attr[] = {
770 &attr_ch0_dimm_label,
771 &attr_ch1_dimm_label,
772 &attr_ch2_dimm_label,
773 &attr_ch3_dimm_label,
774 &attr_ch4_dimm_label,
775 &attr_ch5_dimm_label
776};
777
778/* possible dynamic channel ce_count attribute files */
779CSROWDEV_ATTR(ch0_ce_count,S_IRUGO|S_IWUSR,
780 channel_ce_count_show,
781 NULL,
782 0 );
783CSROWDEV_ATTR(ch1_ce_count,S_IRUGO|S_IWUSR,
784 channel_ce_count_show,
785 NULL,
786 1 );
787CSROWDEV_ATTR(ch2_ce_count,S_IRUGO|S_IWUSR,
788 channel_ce_count_show,
789 NULL,
790 2 );
791CSROWDEV_ATTR(ch3_ce_count,S_IRUGO|S_IWUSR,
792 channel_ce_count_show,
793 NULL,
794 3 );
795CSROWDEV_ATTR(ch4_ce_count,S_IRUGO|S_IWUSR,
796 channel_ce_count_show,
797 NULL,
798 4 );
799CSROWDEV_ATTR(ch5_ce_count,S_IRUGO|S_IWUSR,
800 channel_ce_count_show,
801 NULL,
802 5 );
803
804/* Total possible dynamic ce_count attribute file table */
805static struct csrowdev_attribute *dynamic_csrow_ce_count_attr[] = {
806 &attr_ch0_ce_count,
807 &attr_ch1_ce_count,
808 &attr_ch2_ce_count,
809 &attr_ch3_ce_count,
810 &attr_ch4_ce_count,
811 &attr_ch5_ce_count
812};
813
814
815#define EDAC_NR_CHANNELS 6
816
817/* Create dynamic CHANNEL files, indexed by 'chan', under specifed CSROW */
818static int edac_create_channel_files(struct kobject *kobj, int chan)
819{
820 int err=-ENODEV;
821
822 if (chan >= EDAC_NR_CHANNELS)
823 return err;
824
825 /* create the DIMM label attribute file */
826 err = sysfs_create_file(kobj,
827 (struct attribute *) dynamic_csrow_dimm_attr[chan]);
828
829 if (!err) {
830 /* create the CE Count attribute file */
831 err = sysfs_create_file(kobj,
832 (struct attribute *) dynamic_csrow_ce_count_attr[chan]);
833 } else {
834 debugf1("%s() dimm labels and ce_count files created", __func__);
835 }
836
837 return err;
838}
839
840/* No memory to release for this kobj */
1067static void edac_csrow_instance_release(struct kobject *kobj) 841static void edac_csrow_instance_release(struct kobject *kobj)
1068{ 842{
1069 struct csrow_info *cs; 843 struct csrow_info *cs;
1070 844
1071 debugf1("%s()\n", __func__);
1072 cs = container_of(kobj, struct csrow_info, kobj); 845 cs = container_of(kobj, struct csrow_info, kobj);
1073 complete(&cs->kobj_complete); 846 complete(&cs->kobj_complete);
1074} 847}
1075 848
849/* the kobj_type instance for a CSROW */
1076static struct kobj_type ktype_csrow = { 850static struct kobj_type ktype_csrow = {
1077 .release = edac_csrow_instance_release, 851 .release = edac_csrow_instance_release,
1078 .sysfs_ops = &csrowfs_ops, 852 .sysfs_ops = &csrowfs_ops,
1079 .default_attrs = (struct attribute **) csrow_attr, 853 .default_attrs = (struct attribute **) default_csrow_attr,
1080}; 854};
1081 855
1082/* Create a CSROW object under specifed edac_mc_device */ 856/* Create a CSROW object under specifed edac_mc_device */
1083static int edac_create_csrow_object(struct kobject *edac_mci_kobj, 857static int edac_create_csrow_object(
1084 struct csrow_info *csrow, int index) 858 struct kobject *edac_mci_kobj,
859 struct csrow_info *csrow,
860 int index)
1085{ 861{
1086 int err = 0; 862 int err = 0;
863 int chan;
1087 864
1088 debugf0("%s()\n", __func__);
1089 memset(&csrow->kobj, 0, sizeof(csrow->kobj)); 865 memset(&csrow->kobj, 0, sizeof(csrow->kobj));
1090 866
1091 /* generate ..../edac/mc/mc<id>/csrow<index> */ 867 /* generate ..../edac/mc/mc<id>/csrow<index> */
@@ -1095,21 +871,27 @@ static int edac_create_csrow_object(struct kobject *edac_mci_kobj,
1095 871
1096 /* name this instance of csrow<id> */ 872 /* name this instance of csrow<id> */
1097 err = kobject_set_name(&csrow->kobj,"csrow%d",index); 873 err = kobject_set_name(&csrow->kobj,"csrow%d",index);
874 if (err)
875 goto error_exit;
1098 876
877 /* Instanstiate the csrow object */
878 err = kobject_register(&csrow->kobj);
1099 if (!err) { 879 if (!err) {
1100 /* Instanstiate the csrow object */ 880 /* Create the dyanmic attribute files on this csrow,
1101 err = kobject_register(&csrow->kobj); 881 * namely, the DIMM labels and the channel ce_count
1102 882 */
1103 if (err) 883 for (chan = 0; chan < csrow->nr_channels; chan++) {
1104 debugf0("Failed to register CSROW%d\n",index); 884 err = edac_create_channel_files(&csrow->kobj,chan);
1105 else 885 if (err)
1106 debugf0("Registered CSROW%d\n",index); 886 break;
887 }
1107 } 888 }
1108 889
890error_exit:
1109 return err; 891 return err;
1110} 892}
1111 893
1112/* sysfs data structures and methods for the MCI kobjects */ 894/* default sysfs methods and data structures for the main MCI kobject */
1113 895
1114static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci, 896static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci,
1115 const char *data, size_t count) 897 const char *data, size_t count)
@@ -1135,6 +917,7 @@ static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci,
1135 return count; 917 return count;
1136} 918}
1137 919
920/* default attribute files for the MCI object */
1138static ssize_t mci_ue_count_show(struct mem_ctl_info *mci, char *data) 921static ssize_t mci_ue_count_show(struct mem_ctl_info *mci, char *data)
1139{ 922{
1140 return sprintf(data,"%d\n", mci->ue_count); 923 return sprintf(data,"%d\n", mci->ue_count);
@@ -1160,71 +943,11 @@ static ssize_t mci_seconds_show(struct mem_ctl_info *mci, char *data)
1160 return sprintf(data,"%ld\n", (jiffies - mci->start_time) / HZ); 943 return sprintf(data,"%ld\n", (jiffies - mci->start_time) / HZ);
1161} 944}
1162 945
1163static ssize_t mci_mod_name_show(struct mem_ctl_info *mci, char *data)
1164{
1165 return sprintf(data,"%s %s\n", mci->mod_name, mci->mod_ver);
1166}
1167
1168static ssize_t mci_ctl_name_show(struct mem_ctl_info *mci, char *data) 946static ssize_t mci_ctl_name_show(struct mem_ctl_info *mci, char *data)
1169{ 947{
1170 return sprintf(data,"%s\n", mci->ctl_name); 948 return sprintf(data,"%s\n", mci->ctl_name);
1171} 949}
1172 950
1173static int mci_output_edac_cap(char *buf, unsigned long edac_cap)
1174{
1175 char *p = buf;
1176 int bit_idx;
1177
1178 for (bit_idx = 0; bit_idx < 8 * sizeof(edac_cap); bit_idx++) {
1179 if ((edac_cap >> bit_idx) & 0x1)
1180 p += sprintf(p, "%s ", edac_caps[bit_idx]);
1181 }
1182
1183 return p - buf;
1184}
1185
1186static ssize_t mci_edac_capability_show(struct mem_ctl_info *mci, char *data)
1187{
1188 char *p = data;
1189
1190 p += mci_output_edac_cap(p,mci->edac_ctl_cap);
1191 p += sprintf(p, "\n");
1192 return p - data;
1193}
1194
1195static ssize_t mci_edac_current_capability_show(struct mem_ctl_info *mci,
1196 char *data)
1197{
1198 char *p = data;
1199
1200 p += mci_output_edac_cap(p,mci->edac_cap);
1201 p += sprintf(p, "\n");
1202 return p - data;
1203}
1204
1205static int mci_output_mtype_cap(char *buf, unsigned long mtype_cap)
1206{
1207 char *p = buf;
1208 int bit_idx;
1209
1210 for (bit_idx = 0; bit_idx < 8 * sizeof(mtype_cap); bit_idx++) {
1211 if ((mtype_cap >> bit_idx) & 0x1)
1212 p += sprintf(p, "%s ", mem_types[bit_idx]);
1213 }
1214
1215 return p - buf;
1216}
1217
1218static ssize_t mci_supported_mem_type_show(struct mem_ctl_info *mci,
1219 char *data)
1220{
1221 char *p = data;
1222
1223 p += mci_output_mtype_cap(p,mci->mtype_cap);
1224 p += sprintf(p, "\n");
1225 return p - data;
1226}
1227
1228static ssize_t mci_size_mb_show(struct mem_ctl_info *mci, char *data) 951static ssize_t mci_size_mb_show(struct mem_ctl_info *mci, char *data)
1229{ 952{
1230 int total_pages, csrow_idx; 953 int total_pages, csrow_idx;
@@ -1251,6 +974,7 @@ struct mcidev_attribute {
1251#define to_mci(k) container_of(k, struct mem_ctl_info, edac_mci_kobj) 974#define to_mci(k) container_of(k, struct mem_ctl_info, edac_mci_kobj)
1252#define to_mcidev_attr(a) container_of(a, struct mcidev_attribute, attr) 975#define to_mcidev_attr(a) container_of(a, struct mcidev_attribute, attr)
1253 976
977/* MCI show/store functions for top most object */
1254static ssize_t mcidev_show(struct kobject *kobj, struct attribute *attr, 978static ssize_t mcidev_show(struct kobject *kobj, struct attribute *attr,
1255 char *buffer) 979 char *buffer)
1256{ 980{
@@ -1287,31 +1011,21 @@ struct mcidev_attribute mci_attr_##_name = { \
1287 .store = _store, \ 1011 .store = _store, \
1288}; 1012};
1289 1013
1290/* Control file */ 1014/* default Control file */
1291MCIDEV_ATTR(reset_counters,S_IWUSR,NULL,mci_reset_counters_store); 1015MCIDEV_ATTR(reset_counters,S_IWUSR,NULL,mci_reset_counters_store);
1292 1016
1293/* Attribute files */ 1017/* default Attribute files */
1294MCIDEV_ATTR(mc_name,S_IRUGO,mci_ctl_name_show,NULL); 1018MCIDEV_ATTR(mc_name,S_IRUGO,mci_ctl_name_show,NULL);
1295MCIDEV_ATTR(module_name,S_IRUGO,mci_mod_name_show,NULL);
1296MCIDEV_ATTR(edac_capability,S_IRUGO,mci_edac_capability_show,NULL);
1297MCIDEV_ATTR(size_mb,S_IRUGO,mci_size_mb_show,NULL); 1019MCIDEV_ATTR(size_mb,S_IRUGO,mci_size_mb_show,NULL);
1298MCIDEV_ATTR(seconds_since_reset,S_IRUGO,mci_seconds_show,NULL); 1020MCIDEV_ATTR(seconds_since_reset,S_IRUGO,mci_seconds_show,NULL);
1299MCIDEV_ATTR(ue_noinfo_count,S_IRUGO,mci_ue_noinfo_show,NULL); 1021MCIDEV_ATTR(ue_noinfo_count,S_IRUGO,mci_ue_noinfo_show,NULL);
1300MCIDEV_ATTR(ce_noinfo_count,S_IRUGO,mci_ce_noinfo_show,NULL); 1022MCIDEV_ATTR(ce_noinfo_count,S_IRUGO,mci_ce_noinfo_show,NULL);
1301MCIDEV_ATTR(ue_count,S_IRUGO,mci_ue_count_show,NULL); 1023MCIDEV_ATTR(ue_count,S_IRUGO,mci_ue_count_show,NULL);
1302MCIDEV_ATTR(ce_count,S_IRUGO,mci_ce_count_show,NULL); 1024MCIDEV_ATTR(ce_count,S_IRUGO,mci_ce_count_show,NULL);
1303MCIDEV_ATTR(edac_current_capability,S_IRUGO,
1304 mci_edac_current_capability_show,NULL);
1305MCIDEV_ATTR(supported_mem_type,S_IRUGO,
1306 mci_supported_mem_type_show,NULL);
1307 1025
1308static struct mcidev_attribute *mci_attr[] = { 1026static struct mcidev_attribute *mci_attr[] = {
1309 &mci_attr_reset_counters, 1027 &mci_attr_reset_counters,
1310 &mci_attr_module_name,
1311 &mci_attr_mc_name, 1028 &mci_attr_mc_name,
1312 &mci_attr_edac_capability,
1313 &mci_attr_edac_current_capability,
1314 &mci_attr_supported_mem_type,
1315 &mci_attr_size_mb, 1029 &mci_attr_size_mb,
1316 &mci_attr_seconds_since_reset, 1030 &mci_attr_seconds_since_reset,
1317 &mci_attr_ue_noinfo_count, 1031 &mci_attr_ue_noinfo_count,
@@ -1339,7 +1053,6 @@ static struct kobj_type ktype_mci = {
1339 .default_attrs = (struct attribute **) mci_attr, 1053 .default_attrs = (struct attribute **) mci_attr,
1340}; 1054};
1341 1055
1342#endif /* DISABLE_EDAC_SYSFS */
1343 1056
1344#define EDAC_DEVICE_SYMLINK "device" 1057#define EDAC_DEVICE_SYMLINK "device"
1345 1058
@@ -1352,11 +1065,6 @@ static struct kobj_type ktype_mci = {
1352 * !0 Failure 1065 * !0 Failure
1353 */ 1066 */
1354static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) 1067static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
1355#ifdef DISABLE_EDAC_SYSFS
1356{
1357 return 0;
1358}
1359#else
1360{ 1068{
1361 int i; 1069 int i;
1362 int err; 1070 int err;
@@ -1368,7 +1076,6 @@ static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
1368 1076
1369 /* set the name of the mc<id> object */ 1077 /* set the name of the mc<id> object */
1370 err = kobject_set_name(edac_mci_kobj,"mc%d",mci->mc_idx); 1078 err = kobject_set_name(edac_mci_kobj,"mc%d",mci->mc_idx);
1371
1372 if (err) 1079 if (err)
1373 return err; 1080 return err;
1374 1081
@@ -1378,14 +1085,12 @@ static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
1378 1085
1379 /* register the mc<id> kobject */ 1086 /* register the mc<id> kobject */
1380 err = kobject_register(edac_mci_kobj); 1087 err = kobject_register(edac_mci_kobj);
1381
1382 if (err) 1088 if (err)
1383 return err; 1089 return err;
1384 1090
1385 /* create a symlink for the device */ 1091 /* create a symlink for the device */
1386 err = sysfs_create_link(edac_mci_kobj, &mci->dev->kobj, 1092 err = sysfs_create_link(edac_mci_kobj, &mci->dev->kobj,
1387 EDAC_DEVICE_SYMLINK); 1093 EDAC_DEVICE_SYMLINK);
1388
1389 if (err) 1094 if (err)
1390 goto fail0; 1095 goto fail0;
1391 1096
@@ -1398,7 +1103,6 @@ static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
1398 /* Only expose populated CSROWs */ 1103 /* Only expose populated CSROWs */
1399 if (csrow->nr_pages > 0) { 1104 if (csrow->nr_pages > 0) {
1400 err = edac_create_csrow_object(edac_mci_kobj,csrow,i); 1105 err = edac_create_csrow_object(edac_mci_kobj,csrow,i);
1401
1402 if (err) 1106 if (err)
1403 goto fail1; 1107 goto fail1;
1404 } 1108 }
@@ -1422,14 +1126,12 @@ fail0:
1422 wait_for_completion(&mci->kobj_complete); 1126 wait_for_completion(&mci->kobj_complete);
1423 return err; 1127 return err;
1424} 1128}
1425#endif /* DISABLE_EDAC_SYSFS */
1426 1129
1427/* 1130/*
1428 * remove a Memory Controller instance 1131 * remove a Memory Controller instance
1429 */ 1132 */
1430static void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci) 1133static void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
1431{ 1134{
1432#ifndef DISABLE_EDAC_SYSFS
1433 int i; 1135 int i;
1434 1136
1435 debugf0("%s()\n", __func__); 1137 debugf0("%s()\n", __func__);
@@ -1447,7 +1149,6 @@ static void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
1447 init_completion(&mci->kobj_complete); 1149 init_completion(&mci->kobj_complete);
1448 kobject_unregister(&mci->edac_mci_kobj); 1150 kobject_unregister(&mci->edac_mci_kobj);
1449 wait_for_completion(&mci->kobj_complete); 1151 wait_for_completion(&mci->kobj_complete);
1450#endif /* DISABLE_EDAC_SYSFS */
1451} 1152}
1452 1153
1453/* END OF sysfs data and methods */ 1154/* END OF sysfs data and methods */