blob: e6ecc7da38a5cb0fa9921de062b8cc10fac996d8 [file] [log] [blame]
Alan Coxda9bb1d2006-01-18 17:44:13 -08001/*
2 * edac_mc kernel module
3 * (C) 2005 Linux Networx (http://lnxi.com)
4 * This file may be distributed under the terms of the
5 * GNU General Public License.
6 *
7 * Written by Thayne Harbaugh
8 * Based on work by Dan Hollis <goemon at anime dot net> and others.
9 * http://www.anime.net/~goemon/linux-ecc/
10 *
11 * Modified by Dave Peterson and Doug Thompson
12 *
13 */
14
15
16#include <linux/config.h>
Alan Coxda9bb1d2006-01-18 17:44:13 -080017#include <linux/module.h>
18#include <linux/proc_fs.h>
19#include <linux/kernel.h>
20#include <linux/types.h>
21#include <linux/smp.h>
22#include <linux/init.h>
23#include <linux/sysctl.h>
24#include <linux/highmem.h>
25#include <linux/timer.h>
26#include <linux/slab.h>
27#include <linux/jiffies.h>
28#include <linux/spinlock.h>
29#include <linux/list.h>
30#include <linux/sysdev.h>
31#include <linux/ctype.h>
Dave Petersonf2fe42a2006-03-26 01:38:38 -080032#include <linux/kthread.h>
Alan Coxda9bb1d2006-01-18 17:44:13 -080033
34#include <asm/uaccess.h>
35#include <asm/page.h>
36#include <asm/edac.h>
37
38#include "edac_mc.h"
39
Dave Peterson537fba22006-03-26 01:38:40 -080040#define EDAC_MC_VERSION "Ver: 2.0.0 " __DATE__
Alan Coxda9bb1d2006-01-18 17:44:13 -080041
Dave Petersonceb2ca92006-03-13 21:20:50 -080042/* For now, disable the EDAC sysfs code. The sysfs interface that EDAC
43 * presents to user space needs more thought, and is likely to change
44 * substantially.
45 */
46#define DISABLE_EDAC_SYSFS
47
Alan Coxda9bb1d2006-01-18 17:44:13 -080048#ifdef CONFIG_EDAC_DEBUG
49/* Values of 0 to 4 will generate output */
50int edac_debug_level = 1;
51EXPORT_SYMBOL(edac_debug_level);
52#endif
53
54/* EDAC Controls, setable by module parameter, and sysfs */
55static int log_ue = 1;
56static int log_ce = 1;
Dave Petersonceb2ca92006-03-13 21:20:50 -080057static int panic_on_ue;
Alan Coxda9bb1d2006-01-18 17:44:13 -080058static int poll_msec = 1000;
59
60static int check_pci_parity = 0; /* default YES check PCI parity */
61static int panic_on_pci_parity; /* default no panic on PCI Parity */
62static atomic_t pci_parity_count = ATOMIC_INIT(0);
63
64/* lock to memory controller's control array */
65static DECLARE_MUTEX(mem_ctls_mutex);
66static struct list_head mc_devices = LIST_HEAD_INIT(mc_devices);
67
Dave Petersonf2fe42a2006-03-26 01:38:38 -080068static struct task_struct *edac_thread;
69
Alan Coxda9bb1d2006-01-18 17:44:13 -080070/* Structure of the whitelist and blacklist arrays */
71struct edac_pci_device_list {
72 unsigned int vendor; /* Vendor ID */
73 unsigned int device; /* Deviice ID */
74};
75
76
77#define MAX_LISTED_PCI_DEVICES 32
78
79/* List of PCI devices (vendor-id:device-id) that should be skipped */
80static struct edac_pci_device_list pci_blacklist[MAX_LISTED_PCI_DEVICES];
81static int pci_blacklist_count;
82
83/* List of PCI devices (vendor-id:device-id) that should be scanned */
84static struct edac_pci_device_list pci_whitelist[MAX_LISTED_PCI_DEVICES];
85static int pci_whitelist_count ;
86
87/* START sysfs data and methods */
88
Dave Petersonceb2ca92006-03-13 21:20:50 -080089#ifndef DISABLE_EDAC_SYSFS
90
Alan Coxda9bb1d2006-01-18 17:44:13 -080091static const char *mem_types[] = {
92 [MEM_EMPTY] = "Empty",
93 [MEM_RESERVED] = "Reserved",
94 [MEM_UNKNOWN] = "Unknown",
95 [MEM_FPM] = "FPM",
96 [MEM_EDO] = "EDO",
97 [MEM_BEDO] = "BEDO",
98 [MEM_SDR] = "Unbuffered-SDR",
99 [MEM_RDR] = "Registered-SDR",
100 [MEM_DDR] = "Unbuffered-DDR",
101 [MEM_RDDR] = "Registered-DDR",
102 [MEM_RMBS] = "RMBS"
103};
104
105static const char *dev_types[] = {
106 [DEV_UNKNOWN] = "Unknown",
107 [DEV_X1] = "x1",
108 [DEV_X2] = "x2",
109 [DEV_X4] = "x4",
110 [DEV_X8] = "x8",
111 [DEV_X16] = "x16",
112 [DEV_X32] = "x32",
113 [DEV_X64] = "x64"
114};
115
116static const char *edac_caps[] = {
117 [EDAC_UNKNOWN] = "Unknown",
118 [EDAC_NONE] = "None",
119 [EDAC_RESERVED] = "Reserved",
120 [EDAC_PARITY] = "PARITY",
121 [EDAC_EC] = "EC",
122 [EDAC_SECDED] = "SECDED",
123 [EDAC_S2ECD2ED] = "S2ECD2ED",
124 [EDAC_S4ECD4ED] = "S4ECD4ED",
125 [EDAC_S8ECD8ED] = "S8ECD8ED",
126 [EDAC_S16ECD16ED] = "S16ECD16ED"
127};
128
129
130/* sysfs object: /sys/devices/system/edac */
131static struct sysdev_class edac_class = {
132 set_kset_name("edac"),
133};
134
135/* sysfs objects:
136 * /sys/devices/system/edac/mc
137 * /sys/devices/system/edac/pci
138 */
139static struct kobject edac_memctrl_kobj;
140static struct kobject edac_pci_kobj;
141
142/*
143 * /sys/devices/system/edac/mc;
144 * data structures and methods
145 */
Arjan van de Ven4136cab2006-03-11 03:27:15 -0800146#if 0
Alan Coxda9bb1d2006-01-18 17:44:13 -0800147static ssize_t memctrl_string_show(void *ptr, char *buffer)
148{
149 char *value = (char*) ptr;
150 return sprintf(buffer, "%s\n", value);
151}
Arjan van de Ven4136cab2006-03-11 03:27:15 -0800152#endif
Alan Coxda9bb1d2006-01-18 17:44:13 -0800153
154static ssize_t memctrl_int_show(void *ptr, char *buffer)
155{
156 int *value = (int*) ptr;
157 return sprintf(buffer, "%d\n", *value);
158}
159
160static ssize_t memctrl_int_store(void *ptr, const char *buffer, size_t count)
161{
162 int *value = (int*) ptr;
163
164 if (isdigit(*buffer))
165 *value = simple_strtoul(buffer, NULL, 0);
166
167 return count;
168}
169
170struct memctrl_dev_attribute {
171 struct attribute attr;
172 void *value;
173 ssize_t (*show)(void *,char *);
174 ssize_t (*store)(void *, const char *, size_t);
175};
176
177/* Set of show/store abstract level functions for memory control object */
178static ssize_t
179memctrl_dev_show(struct kobject *kobj, struct attribute *attr, char *buffer)
180{
181 struct memctrl_dev_attribute *memctrl_dev;
182 memctrl_dev = (struct memctrl_dev_attribute*)attr;
183
184 if (memctrl_dev->show)
185 return memctrl_dev->show(memctrl_dev->value, buffer);
186 return -EIO;
187}
188
189static ssize_t
190memctrl_dev_store(struct kobject *kobj, struct attribute *attr,
191 const char *buffer, size_t count)
192{
193 struct memctrl_dev_attribute *memctrl_dev;
194 memctrl_dev = (struct memctrl_dev_attribute*)attr;
195
196 if (memctrl_dev->store)
197 return memctrl_dev->store(memctrl_dev->value, buffer, count);
198 return -EIO;
199}
200
201static struct sysfs_ops memctrlfs_ops = {
202 .show = memctrl_dev_show,
203 .store = memctrl_dev_store
204};
205
206#define MEMCTRL_ATTR(_name,_mode,_show,_store) \
207struct memctrl_dev_attribute attr_##_name = { \
208 .attr = {.name = __stringify(_name), .mode = _mode }, \
209 .value = &_name, \
210 .show = _show, \
211 .store = _store, \
212};
213
214#define MEMCTRL_STRING_ATTR(_name,_data,_mode,_show,_store) \
215struct memctrl_dev_attribute attr_##_name = { \
216 .attr = {.name = __stringify(_name), .mode = _mode }, \
217 .value = _data, \
218 .show = _show, \
219 .store = _store, \
220};
221
222/* cwrow<id> attribute f*/
Arjan van de Ven4136cab2006-03-11 03:27:15 -0800223#if 0
Alan Coxda9bb1d2006-01-18 17:44:13 -0800224MEMCTRL_STRING_ATTR(mc_version,EDAC_MC_VERSION,S_IRUGO,memctrl_string_show,NULL);
Arjan van de Ven4136cab2006-03-11 03:27:15 -0800225#endif
Alan Coxda9bb1d2006-01-18 17:44:13 -0800226
227/* csrow<id> control files */
228MEMCTRL_ATTR(panic_on_ue,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store);
229MEMCTRL_ATTR(log_ue,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store);
230MEMCTRL_ATTR(log_ce,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store);
231MEMCTRL_ATTR(poll_msec,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store);
232
233
234/* Base Attributes of the memory ECC object */
235static struct memctrl_dev_attribute *memctrl_attr[] = {
236 &attr_panic_on_ue,
237 &attr_log_ue,
238 &attr_log_ce,
239 &attr_poll_msec,
Alan Coxda9bb1d2006-01-18 17:44:13 -0800240 NULL,
241};
242
243/* Main MC kobject release() function */
244static void edac_memctrl_master_release(struct kobject *kobj)
245{
Dave Peterson537fba22006-03-26 01:38:40 -0800246 debugf1("%s()\n", __func__);
Alan Coxda9bb1d2006-01-18 17:44:13 -0800247}
248
249static struct kobj_type ktype_memctrl = {
250 .release = edac_memctrl_master_release,
251 .sysfs_ops = &memctrlfs_ops,
252 .default_attrs = (struct attribute **) memctrl_attr,
253};
254
Dave Petersonceb2ca92006-03-13 21:20:50 -0800255#endif /* DISABLE_EDAC_SYSFS */
Alan Coxda9bb1d2006-01-18 17:44:13 -0800256
257/* Initialize the main sysfs entries for edac:
258 * /sys/devices/system/edac
259 *
260 * and children
261 *
262 * Return: 0 SUCCESS
263 * !0 FAILURE
264 */
265static int edac_sysfs_memctrl_setup(void)
Dave Petersonceb2ca92006-03-13 21:20:50 -0800266#ifdef DISABLE_EDAC_SYSFS
267{
268 return 0;
269}
270#else
Alan Coxda9bb1d2006-01-18 17:44:13 -0800271{
272 int err=0;
273
Dave Peterson537fba22006-03-26 01:38:40 -0800274 debugf1("%s()\n", __func__);
Alan Coxda9bb1d2006-01-18 17:44:13 -0800275
276 /* create the /sys/devices/system/edac directory */
277 err = sysdev_class_register(&edac_class);
278 if (!err) {
279 /* Init the MC's kobject */
280 memset(&edac_memctrl_kobj, 0, sizeof (edac_memctrl_kobj));
Alan Coxda9bb1d2006-01-18 17:44:13 -0800281 edac_memctrl_kobj.parent = &edac_class.kset.kobj;
282 edac_memctrl_kobj.ktype = &ktype_memctrl;
283
284 /* generate sysfs "..../edac/mc" */
285 err = kobject_set_name(&edac_memctrl_kobj,"mc");
286 if (!err) {
287 /* FIXME: maybe new sysdev_create_subdir() */
288 err = kobject_register(&edac_memctrl_kobj);
289 if (err) {
290 debugf1("Failed to register '.../edac/mc'\n");
291 } else {
292 debugf1("Registered '.../edac/mc' kobject\n");
293 }
294 }
295 } else {
Dave Peterson537fba22006-03-26 01:38:40 -0800296 debugf1("%s() error=%d\n", __func__, err);
Alan Coxda9bb1d2006-01-18 17:44:13 -0800297 }
298
299 return err;
300}
Dave Petersonceb2ca92006-03-13 21:20:50 -0800301#endif /* DISABLE_EDAC_SYSFS */
Alan Coxda9bb1d2006-01-18 17:44:13 -0800302
303/*
304 * MC teardown:
305 * the '..../edac/mc' kobject followed by '..../edac' itself
306 */
307static void edac_sysfs_memctrl_teardown(void)
308{
Dave Petersonceb2ca92006-03-13 21:20:50 -0800309#ifndef DISABLE_EDAC_SYSFS
Alan Coxda9bb1d2006-01-18 17:44:13 -0800310 debugf0("MC: " __FILE__ ": %s()\n", __func__);
311
312 /* Unregister the MC's kobject */
313 kobject_unregister(&edac_memctrl_kobj);
314
Alan Coxda9bb1d2006-01-18 17:44:13 -0800315 /* Unregister the 'edac' object */
316 sysdev_class_unregister(&edac_class);
Dave Petersonceb2ca92006-03-13 21:20:50 -0800317#endif /* DISABLE_EDAC_SYSFS */
Alan Coxda9bb1d2006-01-18 17:44:13 -0800318}
319
Dave Petersonceb2ca92006-03-13 21:20:50 -0800320#ifndef DISABLE_EDAC_SYSFS
321
Alan Coxda9bb1d2006-01-18 17:44:13 -0800322/*
323 * /sys/devices/system/edac/pci;
324 * data structures and methods
325 */
326
327struct list_control {
328 struct edac_pci_device_list *list;
329 int *count;
330};
331
Arjan van de Ven4136cab2006-03-11 03:27:15 -0800332
333#if 0
Alan Coxda9bb1d2006-01-18 17:44:13 -0800334/* Output the list as: vendor_id:device:id<,vendor_id:device_id> */
335static ssize_t edac_pci_list_string_show(void *ptr, char *buffer)
336{
337 struct list_control *listctl;
338 struct edac_pci_device_list *list;
339 char *p = buffer;
340 int len=0;
341 int i;
342
343 listctl = ptr;
344 list = listctl->list;
345
346 for (i = 0; i < *(listctl->count); i++, list++ ) {
347 if (len > 0)
348 len += snprintf(p + len, (PAGE_SIZE-len), ",");
349
350 len += snprintf(p + len,
351 (PAGE_SIZE-len),
352 "%x:%x",
353 list->vendor,list->device);
354 }
355
356 len += snprintf(p + len,(PAGE_SIZE-len), "\n");
357
358 return (ssize_t) len;
359}
360
361/**
362 *
363 * Scan string from **s to **e looking for one 'vendor:device' tuple
364 * where each field is a hex value
365 *
366 * return 0 if an entry is NOT found
367 * return 1 if an entry is found
368 * fill in *vendor_id and *device_id with values found
369 *
370 * In both cases, make sure *s has been moved forward toward *e
371 */
372static int parse_one_device(const char **s,const char **e,
373 unsigned int *vendor_id, unsigned int *device_id)
374{
375 const char *runner, *p;
376
377 /* if null byte, we are done */
378 if (!**s) {
379 (*s)++; /* keep *s moving */
380 return 0;
381 }
382
383 /* skip over newlines & whitespace */
384 if ((**s == '\n') || isspace(**s)) {
385 (*s)++;
386 return 0;
387 }
388
389 if (!isxdigit(**s)) {
390 (*s)++;
391 return 0;
392 }
393
394 /* parse vendor_id */
395 runner = *s;
396 while (runner < *e) {
397 /* scan for vendor:device delimiter */
398 if (*runner == ':') {
399 *vendor_id = simple_strtol((char*) *s, (char**) &p, 16);
400 runner = p + 1;
401 break;
402 }
403 runner++;
404 }
405
406 if (!isxdigit(*runner)) {
407 *s = ++runner;
408 return 0;
409 }
410
411 /* parse device_id */
412 if (runner < *e) {
413 *device_id = simple_strtol((char*)runner, (char**)&p, 16);
414 runner = p;
415 }
416
417 *s = runner;
418
419 return 1;
420}
421
422static ssize_t edac_pci_list_string_store(void *ptr, const char *buffer,
423 size_t count)
424{
425 struct list_control *listctl;
426 struct edac_pci_device_list *list;
427 unsigned int vendor_id, device_id;
428 const char *s, *e;
429 int *index;
430
431 s = (char*)buffer;
432 e = s + count;
433
434 listctl = ptr;
435 list = listctl->list;
436 index = listctl->count;
437
438 *index = 0;
439 while (*index < MAX_LISTED_PCI_DEVICES) {
440
441 if (parse_one_device(&s,&e,&vendor_id,&device_id)) {
442 list[ *index ].vendor = vendor_id;
443 list[ *index ].device = device_id;
444 (*index)++;
445 }
446
447 /* check for all data consume */
448 if (s >= e)
449 break;
450 }
451
452 return count;
453}
454
Arjan van de Ven4136cab2006-03-11 03:27:15 -0800455#endif
Alan Coxda9bb1d2006-01-18 17:44:13 -0800456static ssize_t edac_pci_int_show(void *ptr, char *buffer)
457{
458 int *value = ptr;
459 return sprintf(buffer,"%d\n",*value);
460}
461
462static ssize_t edac_pci_int_store(void *ptr, const char *buffer, size_t count)
463{
464 int *value = ptr;
465
466 if (isdigit(*buffer))
467 *value = simple_strtoul(buffer,NULL,0);
468
469 return count;
470}
471
472struct edac_pci_dev_attribute {
473 struct attribute attr;
474 void *value;
475 ssize_t (*show)(void *,char *);
476 ssize_t (*store)(void *, const char *,size_t);
477};
478
479/* Set of show/store abstract level functions for PCI Parity object */
480static ssize_t edac_pci_dev_show(struct kobject *kobj, struct attribute *attr,
481 char *buffer)
482{
483 struct edac_pci_dev_attribute *edac_pci_dev;
484 edac_pci_dev= (struct edac_pci_dev_attribute*)attr;
485
486 if (edac_pci_dev->show)
487 return edac_pci_dev->show(edac_pci_dev->value, buffer);
488 return -EIO;
489}
490
491static ssize_t edac_pci_dev_store(struct kobject *kobj, struct attribute *attr,
492 const char *buffer, size_t count)
493{
494 struct edac_pci_dev_attribute *edac_pci_dev;
495 edac_pci_dev= (struct edac_pci_dev_attribute*)attr;
496
497 if (edac_pci_dev->show)
498 return edac_pci_dev->store(edac_pci_dev->value, buffer, count);
499 return -EIO;
500}
501
502static struct sysfs_ops edac_pci_sysfs_ops = {
503 .show = edac_pci_dev_show,
504 .store = edac_pci_dev_store
505};
506
507
508#define EDAC_PCI_ATTR(_name,_mode,_show,_store) \
509struct edac_pci_dev_attribute edac_pci_attr_##_name = { \
510 .attr = {.name = __stringify(_name), .mode = _mode }, \
511 .value = &_name, \
512 .show = _show, \
513 .store = _store, \
514};
515
516#define EDAC_PCI_STRING_ATTR(_name,_data,_mode,_show,_store) \
517struct edac_pci_dev_attribute edac_pci_attr_##_name = { \
518 .attr = {.name = __stringify(_name), .mode = _mode }, \
519 .value = _data, \
520 .show = _show, \
521 .store = _store, \
522};
523
Arjan van de Ven4136cab2006-03-11 03:27:15 -0800524#if 0
Alan Coxda9bb1d2006-01-18 17:44:13 -0800525static struct list_control pci_whitelist_control = {
526 .list = pci_whitelist,
527 .count = &pci_whitelist_count
528};
529
530static struct list_control pci_blacklist_control = {
531 .list = pci_blacklist,
532 .count = &pci_blacklist_count
533};
534
535/* whitelist attribute */
536EDAC_PCI_STRING_ATTR(pci_parity_whitelist,
537 &pci_whitelist_control,
538 S_IRUGO|S_IWUSR,
539 edac_pci_list_string_show,
540 edac_pci_list_string_store);
541
542EDAC_PCI_STRING_ATTR(pci_parity_blacklist,
543 &pci_blacklist_control,
544 S_IRUGO|S_IWUSR,
545 edac_pci_list_string_show,
546 edac_pci_list_string_store);
Arjan van de Ven4136cab2006-03-11 03:27:15 -0800547#endif
Alan Coxda9bb1d2006-01-18 17:44:13 -0800548
549/* PCI Parity control files */
550EDAC_PCI_ATTR(check_pci_parity,S_IRUGO|S_IWUSR,edac_pci_int_show,edac_pci_int_store);
551EDAC_PCI_ATTR(panic_on_pci_parity,S_IRUGO|S_IWUSR,edac_pci_int_show,edac_pci_int_store);
552EDAC_PCI_ATTR(pci_parity_count,S_IRUGO,edac_pci_int_show,NULL);
553
554/* Base Attributes of the memory ECC object */
555static struct edac_pci_dev_attribute *edac_pci_attr[] = {
556 &edac_pci_attr_check_pci_parity,
557 &edac_pci_attr_panic_on_pci_parity,
558 &edac_pci_attr_pci_parity_count,
Alan Coxda9bb1d2006-01-18 17:44:13 -0800559 NULL,
560};
561
562/* No memory to release */
563static void edac_pci_release(struct kobject *kobj)
564{
Dave Peterson537fba22006-03-26 01:38:40 -0800565 debugf1("%s()\n", __func__);
Alan Coxda9bb1d2006-01-18 17:44:13 -0800566}
567
568static struct kobj_type ktype_edac_pci = {
569 .release = edac_pci_release,
570 .sysfs_ops = &edac_pci_sysfs_ops,
571 .default_attrs = (struct attribute **) edac_pci_attr,
572};
573
Dave Petersonceb2ca92006-03-13 21:20:50 -0800574#endif /* DISABLE_EDAC_SYSFS */
575
Alan Coxda9bb1d2006-01-18 17:44:13 -0800576/**
577 * edac_sysfs_pci_setup()
578 *
579 */
580static int edac_sysfs_pci_setup(void)
Dave Petersonceb2ca92006-03-13 21:20:50 -0800581#ifdef DISABLE_EDAC_SYSFS
582{
583 return 0;
584}
585#else
Alan Coxda9bb1d2006-01-18 17:44:13 -0800586{
587 int err;
588
Dave Peterson537fba22006-03-26 01:38:40 -0800589 debugf1("%s()\n", __func__);
Alan Coxda9bb1d2006-01-18 17:44:13 -0800590
591 memset(&edac_pci_kobj, 0, sizeof(edac_pci_kobj));
Alan Coxda9bb1d2006-01-18 17:44:13 -0800592 edac_pci_kobj.parent = &edac_class.kset.kobj;
593 edac_pci_kobj.ktype = &ktype_edac_pci;
594
595 err = kobject_set_name(&edac_pci_kobj, "pci");
596 if (!err) {
597 /* Instanstiate the csrow object */
598 /* FIXME: maybe new sysdev_create_subdir() */
599 err = kobject_register(&edac_pci_kobj);
600 if (err)
601 debugf1("Failed to register '.../edac/pci'\n");
602 else
603 debugf1("Registered '.../edac/pci' kobject\n");
604 }
605 return err;
606}
Dave Petersonceb2ca92006-03-13 21:20:50 -0800607#endif /* DISABLE_EDAC_SYSFS */
Alan Coxda9bb1d2006-01-18 17:44:13 -0800608
609static void edac_sysfs_pci_teardown(void)
610{
Dave Petersonceb2ca92006-03-13 21:20:50 -0800611#ifndef DISABLE_EDAC_SYSFS
Dave Peterson537fba22006-03-26 01:38:40 -0800612 debugf0("%s()\n", __func__);
Alan Coxda9bb1d2006-01-18 17:44:13 -0800613
614 kobject_unregister(&edac_pci_kobj);
Dave Petersonceb2ca92006-03-13 21:20:50 -0800615#endif
Alan Coxda9bb1d2006-01-18 17:44:13 -0800616}
617
Dave Petersonceb2ca92006-03-13 21:20:50 -0800618#ifndef DISABLE_EDAC_SYSFS
619
Alan Coxda9bb1d2006-01-18 17:44:13 -0800620/* EDAC sysfs CSROW data structures and methods */
621
622/* Set of more detailed csrow<id> attribute show/store functions */
623static ssize_t csrow_ch0_dimm_label_show(struct csrow_info *csrow, char *data)
624{
625 ssize_t size = 0;
626
627 if (csrow->nr_channels > 0) {
628 size = snprintf(data, EDAC_MC_LABEL_LEN,"%s\n",
629 csrow->channels[0].label);
630 }
631 return size;
632}
633
634static ssize_t csrow_ch1_dimm_label_show(struct csrow_info *csrow, char *data)
635{
636 ssize_t size = 0;
637
638 if (csrow->nr_channels > 0) {
639 size = snprintf(data, EDAC_MC_LABEL_LEN, "%s\n",
640 csrow->channels[1].label);
641 }
642 return size;
643}
644
645static ssize_t csrow_ch0_dimm_label_store(struct csrow_info *csrow,
646 const char *data, size_t size)
647{
648 ssize_t max_size = 0;
649
650 if (csrow->nr_channels > 0) {
651 max_size = min((ssize_t)size,(ssize_t)EDAC_MC_LABEL_LEN-1);
652 strncpy(csrow->channels[0].label, data, max_size);
653 csrow->channels[0].label[max_size] = '\0';
654 }
655 return size;
656}
657
658static ssize_t csrow_ch1_dimm_label_store(struct csrow_info *csrow,
659 const char *data, size_t size)
660{
661 ssize_t max_size = 0;
662
663 if (csrow->nr_channels > 1) {
664 max_size = min((ssize_t)size,(ssize_t)EDAC_MC_LABEL_LEN-1);
665 strncpy(csrow->channels[1].label, data, max_size);
666 csrow->channels[1].label[max_size] = '\0';
667 }
668 return max_size;
669}
670
671static ssize_t csrow_ue_count_show(struct csrow_info *csrow, char *data)
672{
673 return sprintf(data,"%u\n", csrow->ue_count);
674}
675
676static ssize_t csrow_ce_count_show(struct csrow_info *csrow, char *data)
677{
678 return sprintf(data,"%u\n", csrow->ce_count);
679}
680
681static ssize_t csrow_ch0_ce_count_show(struct csrow_info *csrow, char *data)
682{
683 ssize_t size = 0;
684
685 if (csrow->nr_channels > 0) {
686 size = sprintf(data,"%u\n", csrow->channels[0].ce_count);
687 }
688 return size;
689}
690
691static ssize_t csrow_ch1_ce_count_show(struct csrow_info *csrow, char *data)
692{
693 ssize_t size = 0;
694
695 if (csrow->nr_channels > 1) {
696 size = sprintf(data,"%u\n", csrow->channels[1].ce_count);
697 }
698 return size;
699}
700
701static ssize_t csrow_size_show(struct csrow_info *csrow, char *data)
702{
703 return sprintf(data,"%u\n", PAGES_TO_MiB(csrow->nr_pages));
704}
705
706static ssize_t csrow_mem_type_show(struct csrow_info *csrow, char *data)
707{
708 return sprintf(data,"%s\n", mem_types[csrow->mtype]);
709}
710
711static ssize_t csrow_dev_type_show(struct csrow_info *csrow, char *data)
712{
713 return sprintf(data,"%s\n", dev_types[csrow->dtype]);
714}
715
716static ssize_t csrow_edac_mode_show(struct csrow_info *csrow, char *data)
717{
718 return sprintf(data,"%s\n", edac_caps[csrow->edac_mode]);
719}
720
721struct csrowdev_attribute {
722 struct attribute attr;
723 ssize_t (*show)(struct csrow_info *,char *);
724 ssize_t (*store)(struct csrow_info *, const char *,size_t);
725};
726
727#define to_csrow(k) container_of(k, struct csrow_info, kobj)
728#define to_csrowdev_attr(a) container_of(a, struct csrowdev_attribute, attr)
729
730/* Set of show/store higher level functions for csrow objects */
731static ssize_t csrowdev_show(struct kobject *kobj, struct attribute *attr,
732 char *buffer)
733{
734 struct csrow_info *csrow = to_csrow(kobj);
735 struct csrowdev_attribute *csrowdev_attr = to_csrowdev_attr(attr);
736
737 if (csrowdev_attr->show)
738 return csrowdev_attr->show(csrow, buffer);
739 return -EIO;
740}
741
742static ssize_t csrowdev_store(struct kobject *kobj, struct attribute *attr,
743 const char *buffer, size_t count)
744{
745 struct csrow_info *csrow = to_csrow(kobj);
746 struct csrowdev_attribute * csrowdev_attr = to_csrowdev_attr(attr);
747
748 if (csrowdev_attr->store)
749 return csrowdev_attr->store(csrow, buffer, count);
750 return -EIO;
751}
752
753static struct sysfs_ops csrowfs_ops = {
754 .show = csrowdev_show,
755 .store = csrowdev_store
756};
757
758#define CSROWDEV_ATTR(_name,_mode,_show,_store) \
759struct csrowdev_attribute attr_##_name = { \
760 .attr = {.name = __stringify(_name), .mode = _mode }, \
761 .show = _show, \
762 .store = _store, \
763};
764
765/* cwrow<id>/attribute files */
766CSROWDEV_ATTR(size_mb,S_IRUGO,csrow_size_show,NULL);
767CSROWDEV_ATTR(dev_type,S_IRUGO,csrow_dev_type_show,NULL);
768CSROWDEV_ATTR(mem_type,S_IRUGO,csrow_mem_type_show,NULL);
769CSROWDEV_ATTR(edac_mode,S_IRUGO,csrow_edac_mode_show,NULL);
770CSROWDEV_ATTR(ue_count,S_IRUGO,csrow_ue_count_show,NULL);
771CSROWDEV_ATTR(ce_count,S_IRUGO,csrow_ce_count_show,NULL);
772CSROWDEV_ATTR(ch0_ce_count,S_IRUGO,csrow_ch0_ce_count_show,NULL);
773CSROWDEV_ATTR(ch1_ce_count,S_IRUGO,csrow_ch1_ce_count_show,NULL);
774
775/* control/attribute files */
776CSROWDEV_ATTR(ch0_dimm_label,S_IRUGO|S_IWUSR,
777 csrow_ch0_dimm_label_show,
778 csrow_ch0_dimm_label_store);
779CSROWDEV_ATTR(ch1_dimm_label,S_IRUGO|S_IWUSR,
780 csrow_ch1_dimm_label_show,
781 csrow_ch1_dimm_label_store);
782
783
784/* Attributes of the CSROW<id> object */
785static struct csrowdev_attribute *csrow_attr[] = {
786 &attr_dev_type,
787 &attr_mem_type,
788 &attr_edac_mode,
789 &attr_size_mb,
790 &attr_ue_count,
791 &attr_ce_count,
792 &attr_ch0_ce_count,
793 &attr_ch1_ce_count,
794 &attr_ch0_dimm_label,
795 &attr_ch1_dimm_label,
796 NULL,
797};
798
799
800/* No memory to release */
801static void edac_csrow_instance_release(struct kobject *kobj)
802{
Dave Peterson537fba22006-03-26 01:38:40 -0800803 debugf1("%s()\n", __func__);
Alan Coxda9bb1d2006-01-18 17:44:13 -0800804}
805
806static struct kobj_type ktype_csrow = {
807 .release = edac_csrow_instance_release,
808 .sysfs_ops = &csrowfs_ops,
809 .default_attrs = (struct attribute **) csrow_attr,
810};
811
812/* Create a CSROW object under specifed edac_mc_device */
813static int edac_create_csrow_object(struct kobject *edac_mci_kobj,
814 struct csrow_info *csrow, int index )
815{
816 int err = 0;
817
Dave Peterson537fba22006-03-26 01:38:40 -0800818 debugf0("%s()\n", __func__);
Alan Coxda9bb1d2006-01-18 17:44:13 -0800819
820 memset(&csrow->kobj, 0, sizeof(csrow->kobj));
821
822 /* generate ..../edac/mc/mc<id>/csrow<index> */
823
Alan Coxda9bb1d2006-01-18 17:44:13 -0800824 csrow->kobj.parent = edac_mci_kobj;
825 csrow->kobj.ktype = &ktype_csrow;
826
827 /* name this instance of csrow<id> */
828 err = kobject_set_name(&csrow->kobj,"csrow%d",index);
829 if (!err) {
830 /* Instanstiate the csrow object */
831 err = kobject_register(&csrow->kobj);
832 if (err)
833 debugf0("Failed to register CSROW%d\n",index);
834 else
835 debugf0("Registered CSROW%d\n",index);
836 }
837
838 return err;
839}
840
841/* sysfs data structures and methods for the MCI kobjects */
842
843static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci,
844 const char *data, size_t count )
845{
846 int row, chan;
847
848 mci->ue_noinfo_count = 0;
849 mci->ce_noinfo_count = 0;
850 mci->ue_count = 0;
851 mci->ce_count = 0;
852 for (row = 0; row < mci->nr_csrows; row++) {
853 struct csrow_info *ri = &mci->csrows[row];
854
855 ri->ue_count = 0;
856 ri->ce_count = 0;
857 for (chan = 0; chan < ri->nr_channels; chan++)
858 ri->channels[chan].ce_count = 0;
859 }
860 mci->start_time = jiffies;
861
862 return count;
863}
864
865static ssize_t mci_ue_count_show(struct mem_ctl_info *mci, char *data)
866{
867 return sprintf(data,"%d\n", mci->ue_count);
868}
869
870static ssize_t mci_ce_count_show(struct mem_ctl_info *mci, char *data)
871{
872 return sprintf(data,"%d\n", mci->ce_count);
873}
874
875static ssize_t mci_ce_noinfo_show(struct mem_ctl_info *mci, char *data)
876{
877 return sprintf(data,"%d\n", mci->ce_noinfo_count);
878}
879
880static ssize_t mci_ue_noinfo_show(struct mem_ctl_info *mci, char *data)
881{
882 return sprintf(data,"%d\n", mci->ue_noinfo_count);
883}
884
885static ssize_t mci_seconds_show(struct mem_ctl_info *mci, char *data)
886{
887 return sprintf(data,"%ld\n", (jiffies - mci->start_time) / HZ);
888}
889
890static ssize_t mci_mod_name_show(struct mem_ctl_info *mci, char *data)
891{
892 return sprintf(data,"%s %s\n", mci->mod_name, mci->mod_ver);
893}
894
895static ssize_t mci_ctl_name_show(struct mem_ctl_info *mci, char *data)
896{
897 return sprintf(data,"%s\n", mci->ctl_name);
898}
899
900static int mci_output_edac_cap(char *buf, unsigned long edac_cap)
901{
902 char *p = buf;
903 int bit_idx;
904
905 for (bit_idx = 0; bit_idx < 8 * sizeof(edac_cap); bit_idx++) {
906 if ((edac_cap >> bit_idx) & 0x1)
907 p += sprintf(p, "%s ", edac_caps[bit_idx]);
908 }
909
910 return p - buf;
911}
912
913static ssize_t mci_edac_capability_show(struct mem_ctl_info *mci, char *data)
914{
915 char *p = data;
916
917 p += mci_output_edac_cap(p,mci->edac_ctl_cap);
918 p += sprintf(p, "\n");
919
920 return p - data;
921}
922
923static ssize_t mci_edac_current_capability_show(struct mem_ctl_info *mci,
924 char *data)
925{
926 char *p = data;
927
928 p += mci_output_edac_cap(p,mci->edac_cap);
929 p += sprintf(p, "\n");
930
931 return p - data;
932}
933
934static int mci_output_mtype_cap(char *buf, unsigned long mtype_cap)
935{
936 char *p = buf;
937 int bit_idx;
938
939 for (bit_idx = 0; bit_idx < 8 * sizeof(mtype_cap); bit_idx++) {
940 if ((mtype_cap >> bit_idx) & 0x1)
941 p += sprintf(p, "%s ", mem_types[bit_idx]);
942 }
943
944 return p - buf;
945}
946
947static ssize_t mci_supported_mem_type_show(struct mem_ctl_info *mci, char *data)
948{
949 char *p = data;
950
951 p += mci_output_mtype_cap(p,mci->mtype_cap);
952 p += sprintf(p, "\n");
953
954 return p - data;
955}
956
957static ssize_t mci_size_mb_show(struct mem_ctl_info *mci, char *data)
958{
959 int total_pages, csrow_idx;
960
961 for (total_pages = csrow_idx = 0; csrow_idx < mci->nr_csrows;
962 csrow_idx++) {
963 struct csrow_info *csrow = &mci->csrows[csrow_idx];
964
965 if (!csrow->nr_pages)
966 continue;
967 total_pages += csrow->nr_pages;
968 }
969
970 return sprintf(data,"%u\n", PAGES_TO_MiB(total_pages));
971}
972
973struct mcidev_attribute {
974 struct attribute attr;
975 ssize_t (*show)(struct mem_ctl_info *,char *);
976 ssize_t (*store)(struct mem_ctl_info *, const char *,size_t);
977};
978
979#define to_mci(k) container_of(k, struct mem_ctl_info, edac_mci_kobj)
980#define to_mcidev_attr(a) container_of(a, struct mcidev_attribute, attr)
981
982static ssize_t mcidev_show(struct kobject *kobj, struct attribute *attr,
983 char *buffer)
984{
985 struct mem_ctl_info *mem_ctl_info = to_mci(kobj);
986 struct mcidev_attribute * mcidev_attr = to_mcidev_attr(attr);
987
988 if (mcidev_attr->show)
989 return mcidev_attr->show(mem_ctl_info, buffer);
990 return -EIO;
991}
992
993static ssize_t mcidev_store(struct kobject *kobj, struct attribute *attr,
994 const char *buffer, size_t count)
995{
996 struct mem_ctl_info *mem_ctl_info = to_mci(kobj);
997 struct mcidev_attribute * mcidev_attr = to_mcidev_attr(attr);
998
999 if (mcidev_attr->store)
1000 return mcidev_attr->store(mem_ctl_info, buffer, count);
1001 return -EIO;
1002}
1003
1004static struct sysfs_ops mci_ops = {
1005 .show = mcidev_show,
1006 .store = mcidev_store
1007};
1008
1009#define MCIDEV_ATTR(_name,_mode,_show,_store) \
1010struct mcidev_attribute mci_attr_##_name = { \
1011 .attr = {.name = __stringify(_name), .mode = _mode }, \
1012 .show = _show, \
1013 .store = _store, \
1014};
1015
1016/* Control file */
1017MCIDEV_ATTR(reset_counters,S_IWUSR,NULL,mci_reset_counters_store);
1018
1019/* Attribute files */
1020MCIDEV_ATTR(mc_name,S_IRUGO,mci_ctl_name_show,NULL);
1021MCIDEV_ATTR(module_name,S_IRUGO,mci_mod_name_show,NULL);
1022MCIDEV_ATTR(edac_capability,S_IRUGO,mci_edac_capability_show,NULL);
1023MCIDEV_ATTR(size_mb,S_IRUGO,mci_size_mb_show,NULL);
1024MCIDEV_ATTR(seconds_since_reset,S_IRUGO,mci_seconds_show,NULL);
1025MCIDEV_ATTR(ue_noinfo_count,S_IRUGO,mci_ue_noinfo_show,NULL);
1026MCIDEV_ATTR(ce_noinfo_count,S_IRUGO,mci_ce_noinfo_show,NULL);
1027MCIDEV_ATTR(ue_count,S_IRUGO,mci_ue_count_show,NULL);
1028MCIDEV_ATTR(ce_count,S_IRUGO,mci_ce_count_show,NULL);
1029MCIDEV_ATTR(edac_current_capability,S_IRUGO,
1030 mci_edac_current_capability_show,NULL);
1031MCIDEV_ATTR(supported_mem_type,S_IRUGO,
1032 mci_supported_mem_type_show,NULL);
1033
1034
1035static struct mcidev_attribute *mci_attr[] = {
1036 &mci_attr_reset_counters,
1037 &mci_attr_module_name,
1038 &mci_attr_mc_name,
1039 &mci_attr_edac_capability,
1040 &mci_attr_edac_current_capability,
1041 &mci_attr_supported_mem_type,
1042 &mci_attr_size_mb,
1043 &mci_attr_seconds_since_reset,
1044 &mci_attr_ue_noinfo_count,
1045 &mci_attr_ce_noinfo_count,
1046 &mci_attr_ue_count,
1047 &mci_attr_ce_count,
1048 NULL
1049};
1050
1051
1052/*
1053 * Release of a MC controlling instance
1054 */
1055static void edac_mci_instance_release(struct kobject *kobj)
1056{
1057 struct mem_ctl_info *mci;
1058 mci = container_of(kobj,struct mem_ctl_info,edac_mci_kobj);
1059
Dave Peterson537fba22006-03-26 01:38:40 -08001060 debugf0("%s() idx=%d calling kfree\n", __func__, mci->mc_idx);
Alan Coxda9bb1d2006-01-18 17:44:13 -08001061
1062 kfree(mci);
1063}
1064
1065static struct kobj_type ktype_mci = {
1066 .release = edac_mci_instance_release,
1067 .sysfs_ops = &mci_ops,
1068 .default_attrs = (struct attribute **) mci_attr,
1069};
1070
Dave Petersonceb2ca92006-03-13 21:20:50 -08001071#endif /* DISABLE_EDAC_SYSFS */
1072
Alan Coxda9bb1d2006-01-18 17:44:13 -08001073#define EDAC_DEVICE_SYMLINK "device"
1074
1075/*
1076 * Create a new Memory Controller kobject instance,
1077 * mc<id> under the 'mc' directory
1078 *
1079 * Return:
1080 * 0 Success
1081 * !0 Failure
1082 */
1083static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
Dave Petersonceb2ca92006-03-13 21:20:50 -08001084#ifdef DISABLE_EDAC_SYSFS
1085{
1086 return 0;
1087}
1088#else
Alan Coxda9bb1d2006-01-18 17:44:13 -08001089{
1090 int i;
1091 int err;
1092 struct csrow_info *csrow;
1093 struct kobject *edac_mci_kobj=&mci->edac_mci_kobj;
1094
Dave Peterson537fba22006-03-26 01:38:40 -08001095 debugf0("%s() idx=%d\n", __func__, mci->mc_idx);
Alan Coxda9bb1d2006-01-18 17:44:13 -08001096
1097 memset(edac_mci_kobj, 0, sizeof(*edac_mci_kobj));
Alan Coxda9bb1d2006-01-18 17:44:13 -08001098
1099 /* set the name of the mc<id> object */
1100 err = kobject_set_name(edac_mci_kobj,"mc%d",mci->mc_idx);
1101 if (err)
1102 return err;
1103
1104 /* link to our parent the '..../edac/mc' object */
1105 edac_mci_kobj->parent = &edac_memctrl_kobj;
1106 edac_mci_kobj->ktype = &ktype_mci;
1107
1108 /* register the mc<id> kobject */
1109 err = kobject_register(edac_mci_kobj);
1110 if (err)
1111 return err;
1112
1113 /* create a symlink for the device */
1114 err = sysfs_create_link(edac_mci_kobj, &mci->pdev->dev.kobj,
1115 EDAC_DEVICE_SYMLINK);
Dave Peterson6e5a8742006-03-26 01:38:48 -08001116 if (err)
1117 goto fail0;
Alan Coxda9bb1d2006-01-18 17:44:13 -08001118
1119 /* Make directories for each CSROW object
1120 * under the mc<id> kobject
1121 */
1122 for (i = 0; i < mci->nr_csrows; i++) {
1123
1124 csrow = &mci->csrows[i];
1125
1126 /* Only expose populated CSROWs */
1127 if (csrow->nr_pages > 0) {
1128 err = edac_create_csrow_object(edac_mci_kobj,csrow,i);
1129 if (err)
Dave Peterson6e5a8742006-03-26 01:38:48 -08001130 goto fail1;
Alan Coxda9bb1d2006-01-18 17:44:13 -08001131 }
1132 }
1133
1134 /* Mark this MCI instance as having sysfs entries */
1135 mci->sysfs_active = MCI_SYSFS_ACTIVE;
1136
1137 return 0;
1138
1139
1140 /* CSROW error: backout what has already been registered, */
Dave Peterson6e5a8742006-03-26 01:38:48 -08001141fail1:
Alan Coxda9bb1d2006-01-18 17:44:13 -08001142 for ( i--; i >= 0; i--) {
Dave Peterson6e5a8742006-03-26 01:38:48 -08001143 if (csrow->nr_pages > 0)
Alan Coxda9bb1d2006-01-18 17:44:13 -08001144 kobject_unregister(&mci->csrows[i].kobj);
Alan Coxda9bb1d2006-01-18 17:44:13 -08001145 }
1146
Dave Peterson6e5a8742006-03-26 01:38:48 -08001147fail0:
Alan Coxda9bb1d2006-01-18 17:44:13 -08001148 kobject_unregister(edac_mci_kobj);
Alan Coxda9bb1d2006-01-18 17:44:13 -08001149
1150 return err;
1151}
Dave Petersonceb2ca92006-03-13 21:20:50 -08001152#endif /* DISABLE_EDAC_SYSFS */
Alan Coxda9bb1d2006-01-18 17:44:13 -08001153
1154/*
1155 * remove a Memory Controller instance
1156 */
1157static void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
1158{
Dave Petersonceb2ca92006-03-13 21:20:50 -08001159#ifndef DISABLE_EDAC_SYSFS
Alan Coxda9bb1d2006-01-18 17:44:13 -08001160 int i;
1161
Dave Peterson537fba22006-03-26 01:38:40 -08001162 debugf0("%s()\n", __func__);
Alan Coxda9bb1d2006-01-18 17:44:13 -08001163
1164 /* remove all csrow kobjects */
1165 for (i = 0; i < mci->nr_csrows; i++) {
Dave Peterson6e5a8742006-03-26 01:38:48 -08001166 if (mci->csrows[i].nr_pages > 0)
Alan Coxda9bb1d2006-01-18 17:44:13 -08001167 kobject_unregister(&mci->csrows[i].kobj);
Alan Coxda9bb1d2006-01-18 17:44:13 -08001168 }
1169
1170 sysfs_remove_link(&mci->edac_mci_kobj, EDAC_DEVICE_SYMLINK);
1171
1172 kobject_unregister(&mci->edac_mci_kobj);
Dave Petersonceb2ca92006-03-13 21:20:50 -08001173#endif /* DISABLE_EDAC_SYSFS */
Alan Coxda9bb1d2006-01-18 17:44:13 -08001174}
1175
1176/* END OF sysfs data and methods */
1177
1178#ifdef CONFIG_EDAC_DEBUG
1179
1180EXPORT_SYMBOL(edac_mc_dump_channel);
1181
1182void edac_mc_dump_channel(struct channel_info *chan)
1183{
1184 debugf4("\tchannel = %p\n", chan);
1185 debugf4("\tchannel->chan_idx = %d\n", chan->chan_idx);
1186 debugf4("\tchannel->ce_count = %d\n", chan->ce_count);
1187 debugf4("\tchannel->label = '%s'\n", chan->label);
1188 debugf4("\tchannel->csrow = %p\n\n", chan->csrow);
1189}
1190
1191
1192EXPORT_SYMBOL(edac_mc_dump_csrow);
1193
1194void edac_mc_dump_csrow(struct csrow_info *csrow)
1195{
1196 debugf4("\tcsrow = %p\n", csrow);
1197 debugf4("\tcsrow->csrow_idx = %d\n", csrow->csrow_idx);
1198 debugf4("\tcsrow->first_page = 0x%lx\n",
1199 csrow->first_page);
1200 debugf4("\tcsrow->last_page = 0x%lx\n", csrow->last_page);
1201 debugf4("\tcsrow->page_mask = 0x%lx\n", csrow->page_mask);
1202 debugf4("\tcsrow->nr_pages = 0x%x\n", csrow->nr_pages);
1203 debugf4("\tcsrow->nr_channels = %d\n",
1204 csrow->nr_channels);
1205 debugf4("\tcsrow->channels = %p\n", csrow->channels);
1206 debugf4("\tcsrow->mci = %p\n\n", csrow->mci);
1207}
1208
1209
1210EXPORT_SYMBOL(edac_mc_dump_mci);
1211
1212void edac_mc_dump_mci(struct mem_ctl_info *mci)
1213{
1214 debugf3("\tmci = %p\n", mci);
1215 debugf3("\tmci->mtype_cap = %lx\n", mci->mtype_cap);
1216 debugf3("\tmci->edac_ctl_cap = %lx\n", mci->edac_ctl_cap);
1217 debugf3("\tmci->edac_cap = %lx\n", mci->edac_cap);
1218 debugf4("\tmci->edac_check = %p\n", mci->edac_check);
1219 debugf3("\tmci->nr_csrows = %d, csrows = %p\n",
1220 mci->nr_csrows, mci->csrows);
1221 debugf3("\tpdev = %p\n", mci->pdev);
1222 debugf3("\tmod_name:ctl_name = %s:%s\n",
1223 mci->mod_name, mci->ctl_name);
1224 debugf3("\tpvt_info = %p\n\n", mci->pvt_info);
1225}
1226
1227
1228#endif /* CONFIG_EDAC_DEBUG */
1229
1230/* 'ptr' points to a possibly unaligned item X such that sizeof(X) is 'size'.
1231 * Adjust 'ptr' so that its alignment is at least as stringent as what the
1232 * compiler would provide for X and return the aligned result.
1233 *
1234 * If 'size' is a constant, the compiler will optimize this whole function
1235 * down to either a no-op or the addition of a constant to the value of 'ptr'.
1236 */
1237static inline char * align_ptr (void *ptr, unsigned size)
1238{
1239 unsigned align, r;
1240
1241 /* Here we assume that the alignment of a "long long" is the most
1242 * stringent alignment that the compiler will ever provide by default.
1243 * As far as I know, this is a reasonable assumption.
1244 */
1245 if (size > sizeof(long))
1246 align = sizeof(long long);
1247 else if (size > sizeof(int))
1248 align = sizeof(long);
1249 else if (size > sizeof(short))
1250 align = sizeof(int);
1251 else if (size > sizeof(char))
1252 align = sizeof(short);
1253 else
1254 return (char *) ptr;
1255
1256 r = size % align;
1257
1258 if (r == 0)
1259 return (char *) ptr;
1260
1261 return (char *) (((unsigned long) ptr) + align - r);
1262}
1263
1264
1265EXPORT_SYMBOL(edac_mc_alloc);
1266
1267/**
1268 * edac_mc_alloc: Allocate a struct mem_ctl_info structure
1269 * @size_pvt: size of private storage needed
1270 * @nr_csrows: Number of CWROWS needed for this MC
1271 * @nr_chans: Number of channels for the MC
1272 *
1273 * Everything is kmalloc'ed as one big chunk - more efficient.
1274 * Only can be used if all structures have the same lifetime - otherwise
1275 * you have to allocate and initialize your own structures.
1276 *
1277 * Use edac_mc_free() to free mc structures allocated by this function.
1278 *
1279 * Returns:
1280 * NULL allocation failed
1281 * struct mem_ctl_info pointer
1282 */
1283struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows,
1284 unsigned nr_chans)
1285{
1286 struct mem_ctl_info *mci;
1287 struct csrow_info *csi, *csrow;
1288 struct channel_info *chi, *chp, *chan;
1289 void *pvt;
1290 unsigned size;
1291 int row, chn;
1292
1293 /* Figure out the offsets of the various items from the start of an mc
1294 * structure. We want the alignment of each item to be at least as
1295 * stringent as what the compiler would provide if we could simply
1296 * hardcode everything into a single struct.
1297 */
1298 mci = (struct mem_ctl_info *) 0;
1299 csi = (struct csrow_info *)align_ptr(&mci[1], sizeof(*csi));
1300 chi = (struct channel_info *)
1301 align_ptr(&csi[nr_csrows], sizeof(*chi));
1302 pvt = align_ptr(&chi[nr_chans * nr_csrows], sz_pvt);
1303 size = ((unsigned long) pvt) + sz_pvt;
1304
1305 if ((mci = kmalloc(size, GFP_KERNEL)) == NULL)
1306 return NULL;
1307
1308 /* Adjust pointers so they point within the memory we just allocated
1309 * rather than an imaginary chunk of memory located at address 0.
1310 */
1311 csi = (struct csrow_info *) (((char *) mci) + ((unsigned long) csi));
1312 chi = (struct channel_info *) (((char *) mci) + ((unsigned long) chi));
1313 pvt = sz_pvt ? (((char *) mci) + ((unsigned long) pvt)) : NULL;
1314
1315 memset(mci, 0, size); /* clear all fields */
1316
1317 mci->csrows = csi;
1318 mci->pvt_info = pvt;
1319 mci->nr_csrows = nr_csrows;
1320
1321 for (row = 0; row < nr_csrows; row++) {
1322 csrow = &csi[row];
1323 csrow->csrow_idx = row;
1324 csrow->mci = mci;
1325 csrow->nr_channels = nr_chans;
1326 chp = &chi[row * nr_chans];
1327 csrow->channels = chp;
1328
1329 for (chn = 0; chn < nr_chans; chn++) {
1330 chan = &chp[chn];
1331 chan->chan_idx = chn;
1332 chan->csrow = csrow;
1333 }
1334 }
1335
1336 return mci;
1337}
1338
1339
1340EXPORT_SYMBOL(edac_mc_free);
1341
1342/**
1343 * edac_mc_free: Free a previously allocated 'mci' structure
1344 * @mci: pointer to a struct mem_ctl_info structure
1345 *
1346 * Free up a previously allocated mci structure
1347 * A MCI structure can be in 2 states after being allocated
1348 * by edac_mc_alloc().
1349 * 1) Allocated in a MC driver's probe, but not yet committed
1350 * 2) Allocated and committed, by a call to edac_mc_add_mc()
1351 * edac_mc_add_mc() is the function that adds the sysfs entries
1352 * thus, this free function must determine which state the 'mci'
1353 * structure is in, then either free it directly or
1354 * perform kobject cleanup by calling edac_remove_sysfs_mci_device().
1355 *
1356 * VOID Return
1357 */
1358void edac_mc_free(struct mem_ctl_info *mci)
1359{
1360 /* only if sysfs entries for this mci instance exist
1361 * do we remove them and defer the actual kfree via
1362 * the kobject 'release()' callback.
1363 *
1364 * Otherwise, do a straight kfree now.
1365 */
1366 if (mci->sysfs_active == MCI_SYSFS_ACTIVE)
1367 edac_remove_sysfs_mci_device(mci);
1368 else
1369 kfree(mci);
1370}
1371
1372
1373
1374EXPORT_SYMBOL(edac_mc_find_mci_by_pdev);
1375
1376struct mem_ctl_info *edac_mc_find_mci_by_pdev(struct pci_dev *pdev)
1377{
1378 struct mem_ctl_info *mci;
1379 struct list_head *item;
1380
Dave Peterson537fba22006-03-26 01:38:40 -08001381 debugf3("%s()\n", __func__);
Alan Coxda9bb1d2006-01-18 17:44:13 -08001382
1383 list_for_each(item, &mc_devices) {
1384 mci = list_entry(item, struct mem_ctl_info, link);
1385
1386 if (mci->pdev == pdev)
1387 return mci;
1388 }
1389
1390 return NULL;
1391}
1392
1393static int add_mc_to_global_list (struct mem_ctl_info *mci)
1394{
1395 struct list_head *item, *insert_before;
1396 struct mem_ctl_info *p;
1397 int i;
1398
1399 if (list_empty(&mc_devices)) {
1400 mci->mc_idx = 0;
1401 insert_before = &mc_devices;
1402 } else {
1403 if (edac_mc_find_mci_by_pdev(mci->pdev)) {
Dave Peterson537fba22006-03-26 01:38:40 -08001404 edac_printk(KERN_WARNING, EDAC_MC,
1405 "%s (%s) %s %s already assigned %d\n",
1406 mci->pdev->dev.bus_id,
1407 pci_name(mci->pdev), mci->mod_name,
1408 mci->ctl_name, mci->mc_idx);
Alan Coxda9bb1d2006-01-18 17:44:13 -08001409 return 1;
1410 }
1411
1412 insert_before = NULL;
1413 i = 0;
1414
1415 list_for_each(item, &mc_devices) {
1416 p = list_entry(item, struct mem_ctl_info, link);
1417
1418 if (p->mc_idx != i) {
1419 insert_before = item;
1420 break;
1421 }
1422
1423 i++;
1424 }
1425
1426 mci->mc_idx = i;
1427
1428 if (insert_before == NULL)
1429 insert_before = &mc_devices;
1430 }
1431
1432 list_add_tail_rcu(&mci->link, insert_before);
1433 return 0;
1434}
1435
1436
Dave Petersona1d03fc2006-03-26 01:38:46 -08001437static void complete_mc_list_del (struct rcu_head *head)
1438{
1439 struct mem_ctl_info *mci;
1440
1441 mci = container_of(head, struct mem_ctl_info, rcu);
1442 INIT_LIST_HEAD(&mci->link);
1443 complete(&mci->complete);
1444}
1445
1446
1447static void del_mc_from_global_list (struct mem_ctl_info *mci)
1448{
1449 list_del_rcu(&mci->link);
1450 init_completion(&mci->complete);
1451 call_rcu(&mci->rcu, complete_mc_list_del);
1452 wait_for_completion(&mci->complete);
1453}
1454
Alan Coxda9bb1d2006-01-18 17:44:13 -08001455
1456EXPORT_SYMBOL(edac_mc_add_mc);
1457
1458/**
1459 * edac_mc_add_mc: Insert the 'mci' structure into the mci global list
1460 * @mci: pointer to the mci structure to be added to the list
1461 *
1462 * Return:
1463 * 0 Success
1464 * !0 Failure
1465 */
1466
1467/* FIXME - should a warning be printed if no error detection? correction? */
1468int edac_mc_add_mc(struct mem_ctl_info *mci)
1469{
Dave Peterson537fba22006-03-26 01:38:40 -08001470 debugf0("%s()\n", __func__);
Alan Coxda9bb1d2006-01-18 17:44:13 -08001471#ifdef CONFIG_EDAC_DEBUG
1472 if (edac_debug_level >= 3)
1473 edac_mc_dump_mci(mci);
1474 if (edac_debug_level >= 4) {
1475 int i;
1476
1477 for (i = 0; i < mci->nr_csrows; i++) {
1478 int j;
1479 edac_mc_dump_csrow(&mci->csrows[i]);
1480 for (j = 0; j < mci->csrows[i].nr_channels; j++)
1481 edac_mc_dump_channel(&mci->csrows[i].
1482 channels[j]);
1483 }
1484 }
1485#endif
1486 down(&mem_ctls_mutex);
1487
1488 if (add_mc_to_global_list(mci))
Dave Peterson028a7b62006-03-26 01:38:47 -08001489 goto fail0;
Alan Coxda9bb1d2006-01-18 17:44:13 -08001490
1491 /* set load time so that error rate can be tracked */
1492 mci->start_time = jiffies;
1493
1494 if (edac_create_sysfs_mci_device(mci)) {
Dave Peterson537fba22006-03-26 01:38:40 -08001495 edac_mc_printk(mci, KERN_WARNING,
1496 "failed to create sysfs device\n");
Dave Peterson028a7b62006-03-26 01:38:47 -08001497 goto fail1;
Alan Coxda9bb1d2006-01-18 17:44:13 -08001498 }
1499
1500 /* Report action taken */
Dave Peterson537fba22006-03-26 01:38:40 -08001501 edac_mc_printk(mci, KERN_INFO, "Giving out device to %s %s: PCI %s\n",
1502 mci->mod_name, mci->ctl_name, pci_name(mci->pdev));
Alan Coxda9bb1d2006-01-18 17:44:13 -08001503
Alan Coxda9bb1d2006-01-18 17:44:13 -08001504 up(&mem_ctls_mutex);
Dave Peterson028a7b62006-03-26 01:38:47 -08001505 return 0;
1506
1507fail1:
1508 del_mc_from_global_list(mci);
1509
1510fail0:
1511 up(&mem_ctls_mutex);
1512 return 1;
Alan Coxda9bb1d2006-01-18 17:44:13 -08001513}
1514
1515
Alan Coxda9bb1d2006-01-18 17:44:13 -08001516EXPORT_SYMBOL(edac_mc_del_mc);
1517
1518/**
1519 * edac_mc_del_mc: Remove the specified mci structure from global list
1520 * @mci: Pointer to struct mem_ctl_info structure
1521 *
1522 * Returns:
1523 * 0 Success
1524 * 1 Failure
1525 */
1526int edac_mc_del_mc(struct mem_ctl_info *mci)
1527{
1528 int rc = 1;
1529
Dave Peterson537fba22006-03-26 01:38:40 -08001530 debugf0("MC%d: %s()\n", mci->mc_idx, __func__);
Alan Coxda9bb1d2006-01-18 17:44:13 -08001531 down(&mem_ctls_mutex);
1532 del_mc_from_global_list(mci);
Dave Peterson537fba22006-03-26 01:38:40 -08001533 edac_printk(KERN_INFO, EDAC_MC,
1534 "Removed device %d for %s %s: PCI %s\n", mci->mc_idx,
1535 mci->mod_name, mci->ctl_name, pci_name(mci->pdev));
Alan Coxda9bb1d2006-01-18 17:44:13 -08001536 rc = 0;
1537 up(&mem_ctls_mutex);
1538
1539 return rc;
1540}
1541
1542
1543EXPORT_SYMBOL(edac_mc_scrub_block);
1544
1545void edac_mc_scrub_block(unsigned long page, unsigned long offset,
1546 u32 size)
1547{
1548 struct page *pg;
1549 void *virt_addr;
1550 unsigned long flags = 0;
1551
Dave Peterson537fba22006-03-26 01:38:40 -08001552 debugf3("%s()\n", __func__);
Alan Coxda9bb1d2006-01-18 17:44:13 -08001553
1554 /* ECC error page was not in our memory. Ignore it. */
1555 if(!pfn_valid(page))
1556 return;
1557
1558 /* Find the actual page structure then map it and fix */
1559 pg = pfn_to_page(page);
1560
1561 if (PageHighMem(pg))
1562 local_irq_save(flags);
1563
1564 virt_addr = kmap_atomic(pg, KM_BOUNCE_READ);
1565
1566 /* Perform architecture specific atomic scrub operation */
1567 atomic_scrub(virt_addr + offset, size);
1568
1569 /* Unmap and complete */
1570 kunmap_atomic(virt_addr, KM_BOUNCE_READ);
1571
1572 if (PageHighMem(pg))
1573 local_irq_restore(flags);
1574}
1575
1576
1577/* FIXME - should return -1 */
1578EXPORT_SYMBOL(edac_mc_find_csrow_by_page);
1579
1580int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci,
1581 unsigned long page)
1582{
1583 struct csrow_info *csrows = mci->csrows;
1584 int row, i;
1585
Dave Peterson537fba22006-03-26 01:38:40 -08001586 debugf1("MC%d: %s(): 0x%lx\n", mci->mc_idx, __func__, page);
Alan Coxda9bb1d2006-01-18 17:44:13 -08001587 row = -1;
1588
1589 for (i = 0; i < mci->nr_csrows; i++) {
1590 struct csrow_info *csrow = &csrows[i];
1591
1592 if (csrow->nr_pages == 0)
1593 continue;
1594
Dave Peterson537fba22006-03-26 01:38:40 -08001595 debugf3("MC%d: %s(): first(0x%lx) page(0x%lx) last(0x%lx) "
1596 "mask(0x%lx)\n", mci->mc_idx, __func__,
1597 csrow->first_page, page, csrow->last_page,
1598 csrow->page_mask);
Alan Coxda9bb1d2006-01-18 17:44:13 -08001599
1600 if ((page >= csrow->first_page) &&
1601 (page <= csrow->last_page) &&
1602 ((page & csrow->page_mask) ==
1603 (csrow->first_page & csrow->page_mask))) {
1604 row = i;
1605 break;
1606 }
1607 }
1608
1609 if (row == -1)
Dave Peterson537fba22006-03-26 01:38:40 -08001610 edac_mc_printk(mci, KERN_ERR,
1611 "could not look up page error address %lx\n",
1612 (unsigned long) page);
Alan Coxda9bb1d2006-01-18 17:44:13 -08001613
1614 return row;
1615}
1616
1617
1618EXPORT_SYMBOL(edac_mc_handle_ce);
1619
1620/* FIXME - setable log (warning/emerg) levels */
1621/* FIXME - integrate with evlog: http://evlog.sourceforge.net/ */
1622void edac_mc_handle_ce(struct mem_ctl_info *mci,
1623 unsigned long page_frame_number,
1624 unsigned long offset_in_page,
1625 unsigned long syndrome, int row, int channel,
1626 const char *msg)
1627{
1628 unsigned long remapped_page;
1629
Dave Peterson537fba22006-03-26 01:38:40 -08001630 debugf3("MC%d: %s()\n", mci->mc_idx, __func__);
Alan Coxda9bb1d2006-01-18 17:44:13 -08001631
1632 /* FIXME - maybe make panic on INTERNAL ERROR an option */
1633 if (row >= mci->nr_csrows || row < 0) {
1634 /* something is wrong */
Dave Peterson537fba22006-03-26 01:38:40 -08001635 edac_mc_printk(mci, KERN_ERR,
1636 "INTERNAL ERROR: row out of range "
1637 "(%d >= %d)\n", row, mci->nr_csrows);
Alan Coxda9bb1d2006-01-18 17:44:13 -08001638 edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR");
1639 return;
1640 }
1641 if (channel >= mci->csrows[row].nr_channels || channel < 0) {
1642 /* something is wrong */
Dave Peterson537fba22006-03-26 01:38:40 -08001643 edac_mc_printk(mci, KERN_ERR,
1644 "INTERNAL ERROR: channel out of range "
1645 "(%d >= %d)\n", channel,
1646 mci->csrows[row].nr_channels);
Alan Coxda9bb1d2006-01-18 17:44:13 -08001647 edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR");
1648 return;
1649 }
1650
1651 if (log_ce)
1652 /* FIXME - put in DIMM location */
Dave Peterson537fba22006-03-26 01:38:40 -08001653 edac_mc_printk(mci, KERN_WARNING,
1654 "CE page 0x%lx, offset 0x%lx, grain %d, syndrome "
1655 "0x%lx, row %d, channel %d, label \"%s\": %s\n",
1656 page_frame_number, offset_in_page,
1657 mci->csrows[row].grain, syndrome, row, channel,
1658 mci->csrows[row].channels[channel].label, msg);
Alan Coxda9bb1d2006-01-18 17:44:13 -08001659
1660 mci->ce_count++;
1661 mci->csrows[row].ce_count++;
1662 mci->csrows[row].channels[channel].ce_count++;
1663
1664 if (mci->scrub_mode & SCRUB_SW_SRC) {
1665 /*
1666 * Some MC's can remap memory so that it is still available
1667 * at a different address when PCI devices map into memory.
1668 * MC's that can't do this lose the memory where PCI devices
1669 * are mapped. This mapping is MC dependant and so we call
1670 * back into the MC driver for it to map the MC page to
1671 * a physical (CPU) page which can then be mapped to a virtual
1672 * page - which can then be scrubbed.
1673 */
1674 remapped_page = mci->ctl_page_to_phys ?
1675 mci->ctl_page_to_phys(mci, page_frame_number) :
1676 page_frame_number;
1677
1678 edac_mc_scrub_block(remapped_page, offset_in_page,
1679 mci->csrows[row].grain);
1680 }
1681}
1682
1683
1684EXPORT_SYMBOL(edac_mc_handle_ce_no_info);
1685
1686void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci,
1687 const char *msg)
1688{
1689 if (log_ce)
Dave Peterson537fba22006-03-26 01:38:40 -08001690 edac_mc_printk(mci, KERN_WARNING,
1691 "CE - no information available: %s\n", msg);
Alan Coxda9bb1d2006-01-18 17:44:13 -08001692 mci->ce_noinfo_count++;
1693 mci->ce_count++;
1694}
1695
1696
1697EXPORT_SYMBOL(edac_mc_handle_ue);
1698
1699void edac_mc_handle_ue(struct mem_ctl_info *mci,
1700 unsigned long page_frame_number,
1701 unsigned long offset_in_page, int row,
1702 const char *msg)
1703{
1704 int len = EDAC_MC_LABEL_LEN * 4;
1705 char labels[len + 1];
1706 char *pos = labels;
1707 int chan;
1708 int chars;
1709
Dave Peterson537fba22006-03-26 01:38:40 -08001710 debugf3("MC%d: %s()\n", mci->mc_idx, __func__);
Alan Coxda9bb1d2006-01-18 17:44:13 -08001711
1712 /* FIXME - maybe make panic on INTERNAL ERROR an option */
1713 if (row >= mci->nr_csrows || row < 0) {
1714 /* something is wrong */
Dave Peterson537fba22006-03-26 01:38:40 -08001715 edac_mc_printk(mci, KERN_ERR,
1716 "INTERNAL ERROR: row out of range "
1717 "(%d >= %d)\n", row, mci->nr_csrows);
Alan Coxda9bb1d2006-01-18 17:44:13 -08001718 edac_mc_handle_ue_no_info(mci, "INTERNAL ERROR");
1719 return;
1720 }
1721
1722 chars = snprintf(pos, len + 1, "%s",
1723 mci->csrows[row].channels[0].label);
1724 len -= chars;
1725 pos += chars;
1726 for (chan = 1; (chan < mci->csrows[row].nr_channels) && (len > 0);
1727 chan++) {
1728 chars = snprintf(pos, len + 1, ":%s",
1729 mci->csrows[row].channels[chan].label);
1730 len -= chars;
1731 pos += chars;
1732 }
1733
1734 if (log_ue)
Dave Peterson537fba22006-03-26 01:38:40 -08001735 edac_mc_printk(mci, KERN_EMERG,
1736 "UE page 0x%lx, offset 0x%lx, grain %d, row %d, "
1737 "labels \"%s\": %s\n", page_frame_number,
1738 offset_in_page, mci->csrows[row].grain, row, labels,
1739 msg);
Alan Coxda9bb1d2006-01-18 17:44:13 -08001740
1741 if (panic_on_ue)
1742 panic
1743 ("EDAC MC%d: UE page 0x%lx, offset 0x%lx, grain %d, row %d,"
1744 " labels \"%s\": %s\n", mci->mc_idx,
1745 page_frame_number, offset_in_page,
1746 mci->csrows[row].grain, row, labels, msg);
1747
1748 mci->ue_count++;
1749 mci->csrows[row].ue_count++;
1750}
1751
1752
1753EXPORT_SYMBOL(edac_mc_handle_ue_no_info);
1754
1755void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci,
1756 const char *msg)
1757{
1758 if (panic_on_ue)
1759 panic("EDAC MC%d: Uncorrected Error", mci->mc_idx);
1760
1761 if (log_ue)
Dave Peterson537fba22006-03-26 01:38:40 -08001762 edac_mc_printk(mci, KERN_WARNING,
1763 "UE - no information available: %s\n", msg);
Alan Coxda9bb1d2006-01-18 17:44:13 -08001764 mci->ue_noinfo_count++;
1765 mci->ue_count++;
1766}
1767
1768
1769#ifdef CONFIG_PCI
1770
1771static u16 get_pci_parity_status(struct pci_dev *dev, int secondary)
1772{
1773 int where;
1774 u16 status;
1775
1776 where = secondary ? PCI_SEC_STATUS : PCI_STATUS;
1777 pci_read_config_word(dev, where, &status);
1778
1779 /* If we get back 0xFFFF then we must suspect that the card has been pulled but
1780 the Linux PCI layer has not yet finished cleaning up. We don't want to report
1781 on such devices */
1782
1783 if (status == 0xFFFF) {
1784 u32 sanity;
1785 pci_read_config_dword(dev, 0, &sanity);
1786 if (sanity == 0xFFFFFFFF)
1787 return 0;
1788 }
1789 status &= PCI_STATUS_DETECTED_PARITY | PCI_STATUS_SIG_SYSTEM_ERROR |
1790 PCI_STATUS_PARITY;
1791
1792 if (status)
1793 /* reset only the bits we are interested in */
1794 pci_write_config_word(dev, where, status);
1795
1796 return status;
1797}
1798
1799typedef void (*pci_parity_check_fn_t) (struct pci_dev *dev);
1800
1801/* Clear any PCI parity errors logged by this device. */
1802static void edac_pci_dev_parity_clear( struct pci_dev *dev )
1803{
1804 u8 header_type;
1805
1806 get_pci_parity_status(dev, 0);
1807
1808 /* read the device TYPE, looking for bridges */
1809 pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type);
1810
1811 if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE)
1812 get_pci_parity_status(dev, 1);
1813}
1814
1815/*
1816 * PCI Parity polling
1817 *
1818 */
1819static void edac_pci_dev_parity_test(struct pci_dev *dev)
1820{
1821 u16 status;
1822 u8 header_type;
1823
1824 /* read the STATUS register on this device
1825 */
1826 status = get_pci_parity_status(dev, 0);
1827
1828 debugf2("PCI STATUS= 0x%04x %s\n", status, dev->dev.bus_id );
1829
1830 /* check the status reg for errors */
1831 if (status) {
1832 if (status & (PCI_STATUS_SIG_SYSTEM_ERROR))
Dave Peterson537fba22006-03-26 01:38:40 -08001833 edac_printk(KERN_CRIT, EDAC_PCI,
Alan Coxda9bb1d2006-01-18 17:44:13 -08001834 "Signaled System Error on %s\n",
Dave Peterson537fba22006-03-26 01:38:40 -08001835 pci_name(dev));
Alan Coxda9bb1d2006-01-18 17:44:13 -08001836
1837 if (status & (PCI_STATUS_PARITY)) {
Dave Peterson537fba22006-03-26 01:38:40 -08001838 edac_printk(KERN_CRIT, EDAC_PCI,
Alan Coxda9bb1d2006-01-18 17:44:13 -08001839 "Master Data Parity Error on %s\n",
Dave Peterson537fba22006-03-26 01:38:40 -08001840 pci_name(dev));
Alan Coxda9bb1d2006-01-18 17:44:13 -08001841
1842 atomic_inc(&pci_parity_count);
1843 }
1844
1845 if (status & (PCI_STATUS_DETECTED_PARITY)) {
Dave Peterson537fba22006-03-26 01:38:40 -08001846 edac_printk(KERN_CRIT, EDAC_PCI,
Alan Coxda9bb1d2006-01-18 17:44:13 -08001847 "Detected Parity Error on %s\n",
Dave Peterson537fba22006-03-26 01:38:40 -08001848 pci_name(dev));
Alan Coxda9bb1d2006-01-18 17:44:13 -08001849
1850 atomic_inc(&pci_parity_count);
1851 }
1852 }
1853
1854 /* read the device TYPE, looking for bridges */
1855 pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type);
1856
1857 debugf2("PCI HEADER TYPE= 0x%02x %s\n", header_type, dev->dev.bus_id );
1858
1859 if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
1860 /* On bridges, need to examine secondary status register */
1861 status = get_pci_parity_status(dev, 1);
1862
1863 debugf2("PCI SEC_STATUS= 0x%04x %s\n",
1864 status, dev->dev.bus_id );
1865
1866 /* check the secondary status reg for errors */
1867 if (status) {
1868 if (status & (PCI_STATUS_SIG_SYSTEM_ERROR))
Dave Peterson537fba22006-03-26 01:38:40 -08001869 edac_printk(KERN_CRIT, EDAC_PCI, "Bridge "
Alan Coxda9bb1d2006-01-18 17:44:13 -08001870 "Signaled System Error on %s\n",
Dave Peterson537fba22006-03-26 01:38:40 -08001871 pci_name(dev));
Alan Coxda9bb1d2006-01-18 17:44:13 -08001872
1873 if (status & (PCI_STATUS_PARITY)) {
Dave Peterson537fba22006-03-26 01:38:40 -08001874 edac_printk(KERN_CRIT, EDAC_PCI, "Bridge "
1875 "Master Data Parity Error on "
1876 "%s\n", pci_name(dev));
Alan Coxda9bb1d2006-01-18 17:44:13 -08001877
1878 atomic_inc(&pci_parity_count);
1879 }
1880
1881 if (status & (PCI_STATUS_DETECTED_PARITY)) {
Dave Peterson537fba22006-03-26 01:38:40 -08001882 edac_printk(KERN_CRIT, EDAC_PCI, "Bridge "
Alan Coxda9bb1d2006-01-18 17:44:13 -08001883 "Detected Parity Error on %s\n",
Dave Peterson537fba22006-03-26 01:38:40 -08001884 pci_name(dev));
Alan Coxda9bb1d2006-01-18 17:44:13 -08001885
1886 atomic_inc(&pci_parity_count);
1887 }
1888 }
1889 }
1890}
1891
1892/*
1893 * check_dev_on_list: Scan for a PCI device on a white/black list
1894 * @list: an EDAC &edac_pci_device_list white/black list pointer
1895 * @free_index: index of next free entry on the list
1896 * @pci_dev: PCI Device pointer
1897 *
1898 * see if list contains the device.
1899 *
1900 * Returns: 0 not found
1901 * 1 found on list
1902 */
1903static int check_dev_on_list(struct edac_pci_device_list *list, int free_index,
1904 struct pci_dev *dev)
1905{
1906 int i;
1907 int rc = 0; /* Assume not found */
1908 unsigned short vendor=dev->vendor;
1909 unsigned short device=dev->device;
1910
1911 /* Scan the list, looking for a vendor/device match
1912 */
1913 for (i = 0; i < free_index; i++, list++ ) {
1914 if ( (list->vendor == vendor ) &&
1915 (list->device == device )) {
1916 rc = 1;
1917 break;
1918 }
1919 }
1920
1921 return rc;
1922}
1923
1924/*
1925 * pci_dev parity list iterator
1926 * Scan the PCI device list for one iteration, looking for SERRORs
1927 * Master Parity ERRORS or Parity ERRORs on primary or secondary devices
1928 */
1929static inline void edac_pci_dev_parity_iterator(pci_parity_check_fn_t fn)
1930{
1931 struct pci_dev *dev=NULL;
1932
1933 /* request for kernel access to the next PCI device, if any,
1934 * and while we are looking at it have its reference count
1935 * bumped until we are done with it
1936 */
1937 while((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
1938
1939 /* if whitelist exists then it has priority, so only scan those
1940 * devices on the whitelist
1941 */
1942 if (pci_whitelist_count > 0 ) {
1943 if (check_dev_on_list(pci_whitelist,
1944 pci_whitelist_count, dev))
1945 fn(dev);
1946 } else {
1947 /*
1948 * if no whitelist, then check if this devices is
1949 * blacklisted
1950 */
1951 if (!check_dev_on_list(pci_blacklist,
1952 pci_blacklist_count, dev))
1953 fn(dev);
1954 }
1955 }
1956}
1957
1958static void do_pci_parity_check(void)
1959{
1960 unsigned long flags;
1961 int before_count;
1962
Dave Peterson537fba22006-03-26 01:38:40 -08001963 debugf3("%s()\n", __func__);
Alan Coxda9bb1d2006-01-18 17:44:13 -08001964
1965 if (!check_pci_parity)
1966 return;
1967
1968 before_count = atomic_read(&pci_parity_count);
1969
1970 /* scan all PCI devices looking for a Parity Error on devices and
1971 * bridges
1972 */
1973 local_irq_save(flags);
1974 edac_pci_dev_parity_iterator(edac_pci_dev_parity_test);
1975 local_irq_restore(flags);
1976
1977 /* Only if operator has selected panic on PCI Error */
1978 if (panic_on_pci_parity) {
1979 /* If the count is different 'after' from 'before' */
1980 if (before_count != atomic_read(&pci_parity_count))
1981 panic("EDAC: PCI Parity Error");
1982 }
1983}
1984
1985
1986static inline void clear_pci_parity_errors(void)
1987{
1988 /* Clear any PCI bus parity errors that devices initially have logged
1989 * in their registers.
1990 */
1991 edac_pci_dev_parity_iterator(edac_pci_dev_parity_clear);
1992}
1993
1994
1995#else /* CONFIG_PCI */
1996
1997
1998static inline void do_pci_parity_check(void)
1999{
2000 /* no-op */
2001}
2002
2003
2004static inline void clear_pci_parity_errors(void)
2005{
2006 /* no-op */
2007}
2008
2009
2010#endif /* CONFIG_PCI */
2011
2012/*
2013 * Iterate over all MC instances and check for ECC, et al, errors
2014 */
2015static inline void check_mc_devices (void)
2016{
2017 unsigned long flags;
2018 struct list_head *item;
2019 struct mem_ctl_info *mci;
2020
Dave Peterson537fba22006-03-26 01:38:40 -08002021 debugf3("%s()\n", __func__);
Alan Coxda9bb1d2006-01-18 17:44:13 -08002022
2023 /* during poll, have interrupts off */
2024 local_irq_save(flags);
2025
2026 list_for_each(item, &mc_devices) {
2027 mci = list_entry(item, struct mem_ctl_info, link);
2028
2029 if (mci->edac_check != NULL)
2030 mci->edac_check(mci);
2031 }
2032
2033 local_irq_restore(flags);
2034}
2035
2036
2037/*
2038 * Check MC status every poll_msec.
2039 * Check PCI status every poll_msec as well.
2040 *
2041 * This where the work gets done for edac.
2042 *
2043 * SMP safe, doesn't use NMI, and auto-rate-limits.
2044 */
2045static void do_edac_check(void)
2046{
Dave Peterson537fba22006-03-26 01:38:40 -08002047 debugf3("%s()\n", __func__);
Alan Coxda9bb1d2006-01-18 17:44:13 -08002048 check_mc_devices();
Alan Coxda9bb1d2006-01-18 17:44:13 -08002049 do_pci_parity_check();
2050}
2051
Alan Coxda9bb1d2006-01-18 17:44:13 -08002052static int edac_kernel_thread(void *arg)
2053{
Dave Petersonf2fe42a2006-03-26 01:38:38 -08002054 while (!kthread_should_stop()) {
2055 do_edac_check();
Alan Coxda9bb1d2006-01-18 17:44:13 -08002056
2057 /* goto sleep for the interval */
Dave Petersonf2fe42a2006-03-26 01:38:38 -08002058 schedule_timeout_interruptible((HZ * poll_msec) / 1000);
Alan Coxda9bb1d2006-01-18 17:44:13 -08002059 try_to_freeze();
2060 }
2061
Alan Coxda9bb1d2006-01-18 17:44:13 -08002062 return 0;
2063}
2064
2065/*
2066 * edac_mc_init
2067 * module initialization entry point
2068 */
2069static int __init edac_mc_init(void)
2070{
Dave Peterson537fba22006-03-26 01:38:40 -08002071 edac_printk(KERN_INFO, EDAC_MC, EDAC_MC_VERSION "\n");
Alan Coxda9bb1d2006-01-18 17:44:13 -08002072
2073 /*
2074 * Harvest and clear any boot/initialization PCI parity errors
2075 *
2076 * FIXME: This only clears errors logged by devices present at time of
2077 * module initialization. We should also do an initial clear
2078 * of each newly hotplugged device.
2079 */
2080 clear_pci_parity_errors();
2081
Alan Coxda9bb1d2006-01-18 17:44:13 -08002082 /* Create the MC sysfs entires */
2083 if (edac_sysfs_memctrl_setup()) {
Dave Peterson537fba22006-03-26 01:38:40 -08002084 edac_printk(KERN_ERR, EDAC_MC,
2085 "Error initializing sysfs code\n");
Alan Coxda9bb1d2006-01-18 17:44:13 -08002086 return -ENODEV;
2087 }
2088
2089 /* Create the PCI parity sysfs entries */
2090 if (edac_sysfs_pci_setup()) {
2091 edac_sysfs_memctrl_teardown();
Dave Peterson537fba22006-03-26 01:38:40 -08002092 edac_printk(KERN_ERR, EDAC_MC,
2093 "EDAC PCI: Error initializing sysfs code\n");
Alan Coxda9bb1d2006-01-18 17:44:13 -08002094 return -ENODEV;
2095 }
2096
Alan Coxda9bb1d2006-01-18 17:44:13 -08002097 /* create our kernel thread */
Dave Petersonf2fe42a2006-03-26 01:38:38 -08002098 edac_thread = kthread_run(edac_kernel_thread, NULL, "kedac");
2099 if (IS_ERR(edac_thread)) {
Alan Coxda9bb1d2006-01-18 17:44:13 -08002100 /* remove the sysfs entries */
2101 edac_sysfs_memctrl_teardown();
2102 edac_sysfs_pci_teardown();
Dave Petersonf2fe42a2006-03-26 01:38:38 -08002103 return PTR_ERR(edac_thread);
Alan Coxda9bb1d2006-01-18 17:44:13 -08002104 }
2105
Alan Coxda9bb1d2006-01-18 17:44:13 -08002106 return 0;
2107}
2108
2109
2110/*
2111 * edac_mc_exit()
2112 * module exit/termination functioni
2113 */
2114static void __exit edac_mc_exit(void)
2115{
Dave Peterson537fba22006-03-26 01:38:40 -08002116 debugf0("%s()\n", __func__);
Alan Coxda9bb1d2006-01-18 17:44:13 -08002117
Dave Petersonf2fe42a2006-03-26 01:38:38 -08002118 kthread_stop(edac_thread);
Alan Coxda9bb1d2006-01-18 17:44:13 -08002119
2120 /* tear down the sysfs device */
2121 edac_sysfs_memctrl_teardown();
2122 edac_sysfs_pci_teardown();
2123}
2124
2125
2126
2127
2128module_init(edac_mc_init);
2129module_exit(edac_mc_exit);
2130
2131MODULE_LICENSE("GPL");
2132MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh et al\n"
2133 "Based on.work by Dan Hollis et al");
2134MODULE_DESCRIPTION("Core library routines for MC reporting");
2135
2136module_param(panic_on_ue, int, 0644);
2137MODULE_PARM_DESC(panic_on_ue, "Panic on uncorrected error: 0=off 1=on");
2138module_param(check_pci_parity, int, 0644);
2139MODULE_PARM_DESC(check_pci_parity, "Check for PCI bus parity errors: 0=off 1=on");
2140module_param(panic_on_pci_parity, int, 0644);
2141MODULE_PARM_DESC(panic_on_pci_parity, "Panic on PCI Bus Parity error: 0=off 1=on");
2142module_param(log_ue, int, 0644);
2143MODULE_PARM_DESC(log_ue, "Log uncorrectable error to console: 0=off 1=on");
2144module_param(log_ce, int, 0644);
2145MODULE_PARM_DESC(log_ce, "Log correctable error to console: 0=off 1=on");
2146module_param(poll_msec, int, 0644);
2147MODULE_PARM_DESC(poll_msec, "Polling period in milliseconds");
2148#ifdef CONFIG_EDAC_DEBUG
2149module_param(edac_debug_level, int, 0644);
2150MODULE_PARM_DESC(edac_debug_level, "Debug level");
2151#endif