drivers/edac: add new nmi rescan
[safe/jmp/linux-2.6] / drivers / edac / edac_module.c
1
2 #include <linux/freezer.h>
3 #include <linux/kthread.h>
4 #include <linux/edac.h>
5
6 #include "edac_mc.h"
7 #include "edac_module.h"
8
9 #define EDAC_MC_VERSION "Ver: 2.0.3" __DATE__
10
11 #ifdef CONFIG_EDAC_DEBUG
12 /* Values of 0 to 4 will generate output */
13 int edac_debug_level = 1;
14 EXPORT_SYMBOL_GPL(edac_debug_level);
15 #endif
16
17 /* scope is to module level only */
18 struct workqueue_struct *edac_workqueue;
19
20 /* private to this file */
21 static struct task_struct *edac_thread;
22
23
24 /*
25  * sysfs object: /sys/devices/system/edac
26  *      need to export to other files in this modules
27  */
28 static struct sysdev_class edac_class = {
29         set_kset_name("edac"),
30 };
31 static int edac_class_valid = 0;
32
33 /*
34  * edac_get_edac_class()
35  *
36  *      return pointer to the edac class of 'edac'
37  */
38 struct sysdev_class *edac_get_edac_class(void)
39 {
40         struct sysdev_class *classptr=NULL;
41
42         if (edac_class_valid)
43                 classptr = &edac_class;
44
45         return classptr;
46 }
47
48 /*
49  * edac_register_sysfs_edac_name()
50  *
51  *      register the 'edac' into /sys/devices/system
52  *
53  * return:
54  *      0  success
55  *      !0 error
56  */
57 static int edac_register_sysfs_edac_name(void)
58 {
59         int err;
60
61         /* create the /sys/devices/system/edac directory */
62         err = sysdev_class_register(&edac_class);
63
64         if (err) {
65                 debugf1("%s() error=%d\n", __func__, err);
66                 return err;
67         }
68
69         edac_class_valid = 1;
70         return 0;
71 }
72
73 /*
74  * sysdev_class_unregister()
75  *
76  *      unregister the 'edac' from /sys/devices/system
77  */
78 static void edac_unregister_sysfs_edac_name(void)
79 {
80         /* only if currently registered, then unregister it */
81         if (edac_class_valid)
82                 sysdev_class_unregister(&edac_class);
83
84         edac_class_valid = 0;
85 }
86
87
88 /*
89  * Check MC status every edac_get_poll_msec().
90  * Check PCI status every edac_get_poll_msec() as well.
91  *
92  * This where the work gets done for edac.
93  *
94  * SMP safe, doesn't use NMI, and auto-rate-limits.
95  */
96 static void do_edac_check(void)
97 {
98         debugf3("%s()\n", __func__);
99
100         /* perform the poll activities */
101         edac_check_mc_devices();
102         edac_pci_do_parity_check();
103 }
104
105 /*
106  * handler for EDAC to check if NMI type handler has asserted interrupt
107  */
108 static int edac_assert_error_check_and_clear(void)
109 {
110         int vreg;
111
112         if(edac_op_state == EDAC_OPSTATE_POLL)
113                 return 1;
114
115         vreg = atomic_read(&edac_err_assert);
116         if(vreg) {
117                 atomic_set(&edac_err_assert, 0);
118                 return 1;
119         }
120
121         return 0;
122 }
123
124 /*
125  * Action thread for EDAC to perform the POLL operations
126  */
127 static int edac_kernel_thread(void *arg)
128 {
129         int msec;
130
131         while (!kthread_should_stop()) {
132                 if(edac_assert_error_check_and_clear())
133                         do_edac_check();
134
135                 /* goto sleep for the interval */
136                 msec = (HZ * edac_get_poll_msec()) / 1000;
137                 schedule_timeout_interruptible(msec);
138                 try_to_freeze();
139         }
140
141         return 0;
142 }
143
144 /*
145  * edac_workqueue_setup
146  *      initialize the edac work queue for polling operations
147  */
148 static int edac_workqueue_setup(void)
149 {
150         edac_workqueue = create_singlethread_workqueue("edac-poller");
151         if (edac_workqueue == NULL)
152                 return -ENODEV;
153         else
154                 return 0;
155 }
156
157 /*
158  * edac_workqueue_teardown
159  *      teardown the edac workqueue
160  */
161 static void edac_workqueue_teardown(void)
162 {
163         if (edac_workqueue) {
164                 flush_workqueue(edac_workqueue);
165                 destroy_workqueue(edac_workqueue);
166                 edac_workqueue = NULL;
167         }
168 }
169
170
171 /*
172  * edac_init
173  *      module initialization entry point
174  */
175 static int __init edac_init(void)
176 {
177         int err = 0;
178
179         edac_printk(KERN_INFO, EDAC_MC, EDAC_MC_VERSION "\n");
180
181         /*
182          * Harvest and clear any boot/initialization PCI parity errors
183          *
184          * FIXME: This only clears errors logged by devices present at time of
185          *      module initialization.  We should also do an initial clear
186          *      of each newly hotplugged device.
187          */
188         edac_pci_clear_parity_errors();
189
190         /*
191          * perform the registration of the /sys/devices/system/edac object
192          */
193         if (edac_register_sysfs_edac_name()) {
194                 edac_printk(KERN_ERR, EDAC_MC,
195                         "Error initializing 'edac' kobject\n");
196                 err = -ENODEV;
197                 goto error;
198         }
199
200         /* Create the MC sysfs entries, must be first
201          */
202         if (edac_sysfs_memctrl_setup()) {
203                 edac_printk(KERN_ERR, EDAC_MC,
204                         "Error initializing sysfs code\n");
205                 err = -ENODEV;
206                 goto error_sysfs;
207         }
208
209         /* Create the PCI parity sysfs entries */
210         if (edac_sysfs_pci_setup()) {
211                 edac_printk(KERN_ERR, EDAC_MC,
212                         "PCI: Error initializing sysfs code\n");
213                 err = -ENODEV;
214                 goto error_mem;
215         }
216
217         /* Setup/Initialize the edac_device system */
218         err = edac_workqueue_setup();
219         if (err) {
220                 edac_printk(KERN_ERR, EDAC_MC, "init WorkQueue failure\n");
221                 goto error_pci;
222         }
223
224         /* create our kernel thread */
225         edac_thread = kthread_run(edac_kernel_thread, NULL, "kedac");
226
227         if (IS_ERR(edac_thread)) {
228                 err = PTR_ERR(edac_thread);
229                 goto error_work;
230         }
231
232         return 0;
233
234         /* Error teardown stack */
235 error_work:
236         edac_workqueue_teardown();
237 error_pci:
238         edac_sysfs_pci_teardown();
239 error_mem:
240         edac_sysfs_memctrl_teardown();
241 error_sysfs:
242         edac_unregister_sysfs_edac_name();
243 error:
244         return err;
245 }
246
247 /*
248  * edac_exit()
249  *      module exit/termination function
250  */
251 static void __exit edac_exit(void)
252 {
253         debugf0("%s()\n", __func__);
254         kthread_stop(edac_thread);
255
256         /* tear down the various subsystems*/
257         edac_workqueue_teardown();
258         edac_sysfs_memctrl_teardown();
259         edac_sysfs_pci_teardown();
260         edac_unregister_sysfs_edac_name();
261 }
262
263 /*
264  * Inform the kernel of our entry and exit points
265  */
266 module_init(edac_init);
267 module_exit(edac_exit);
268
269 MODULE_LICENSE("GPL");
270 MODULE_AUTHOR("Doug Thompson www.softwarebitmaker.com, et al");
271 MODULE_DESCRIPTION("Core library routines for EDAC reporting");
272
273 /* refer to *_sysfs.c files for parameters that are exported via sysfs */
274
275 #ifdef CONFIG_EDAC_DEBUG
276 module_param(edac_debug_level, int, 0644);
277 MODULE_PARM_DESC(edac_debug_level, "Debug level");
278 #endif
279