2 #include <linux/freezer.h>
3 #include <linux/kthread.h>
4 #include <linux/edac.h>
7 #include "edac_module.h"
9 #define EDAC_MC_VERSION "Ver: 2.0.3" __DATE__
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);
17 /* scope is to module level only */
18 struct workqueue_struct *edac_workqueue;
20 /* private to this file */
21 static struct task_struct *edac_thread;
25 * sysfs object: /sys/devices/system/edac
26 * need to export to other files in this modules
28 static struct sysdev_class edac_class = {
29 set_kset_name("edac"),
31 static int edac_class_valid = 0;
34 * edac_get_edac_class()
36 * return pointer to the edac class of 'edac'
38 struct sysdev_class *edac_get_edac_class(void)
40 struct sysdev_class *classptr=NULL;
43 classptr = &edac_class;
49 * edac_register_sysfs_edac_name()
51 * register the 'edac' into /sys/devices/system
57 static int edac_register_sysfs_edac_name(void)
61 /* create the /sys/devices/system/edac directory */
62 err = sysdev_class_register(&edac_class);
65 debugf1("%s() error=%d\n", __func__, err);
74 * sysdev_class_unregister()
76 * unregister the 'edac' from /sys/devices/system
78 static void edac_unregister_sysfs_edac_name(void)
80 /* only if currently registered, then unregister it */
82 sysdev_class_unregister(&edac_class);
89 * Check MC status every edac_get_poll_msec().
90 * Check PCI status every edac_get_poll_msec() as well.
92 * This where the work gets done for edac.
94 * SMP safe, doesn't use NMI, and auto-rate-limits.
96 static void do_edac_check(void)
98 debugf3("%s()\n", __func__);
100 /* perform the poll activities */
101 edac_check_mc_devices();
102 edac_pci_do_parity_check();
106 * handler for EDAC to check if NMI type handler has asserted interrupt
108 static int edac_assert_error_check_and_clear(void)
112 if(edac_op_state == EDAC_OPSTATE_POLL)
115 vreg = atomic_read(&edac_err_assert);
117 atomic_set(&edac_err_assert, 0);
125 * Action thread for EDAC to perform the POLL operations
127 static int edac_kernel_thread(void *arg)
131 while (!kthread_should_stop()) {
132 if(edac_assert_error_check_and_clear())
135 /* goto sleep for the interval */
136 msec = (HZ * edac_get_poll_msec()) / 1000;
137 schedule_timeout_interruptible(msec);
145 * edac_workqueue_setup
146 * initialize the edac work queue for polling operations
148 static int edac_workqueue_setup(void)
150 edac_workqueue = create_singlethread_workqueue("edac-poller");
151 if (edac_workqueue == NULL)
158 * edac_workqueue_teardown
159 * teardown the edac workqueue
161 static void edac_workqueue_teardown(void)
163 if (edac_workqueue) {
164 flush_workqueue(edac_workqueue);
165 destroy_workqueue(edac_workqueue);
166 edac_workqueue = NULL;
173 * module initialization entry point
175 static int __init edac_init(void)
179 edac_printk(KERN_INFO, EDAC_MC, EDAC_MC_VERSION "\n");
182 * Harvest and clear any boot/initialization PCI parity errors
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.
188 edac_pci_clear_parity_errors();
191 * perform the registration of the /sys/devices/system/edac object
193 if (edac_register_sysfs_edac_name()) {
194 edac_printk(KERN_ERR, EDAC_MC,
195 "Error initializing 'edac' kobject\n");
200 /* Create the MC sysfs entries, must be first
202 if (edac_sysfs_memctrl_setup()) {
203 edac_printk(KERN_ERR, EDAC_MC,
204 "Error initializing sysfs code\n");
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");
217 /* Setup/Initialize the edac_device system */
218 err = edac_workqueue_setup();
220 edac_printk(KERN_ERR, EDAC_MC, "init WorkQueue failure\n");
224 /* create our kernel thread */
225 edac_thread = kthread_run(edac_kernel_thread, NULL, "kedac");
227 if (IS_ERR(edac_thread)) {
228 err = PTR_ERR(edac_thread);
234 /* Error teardown stack */
236 edac_workqueue_teardown();
238 edac_sysfs_pci_teardown();
240 edac_sysfs_memctrl_teardown();
242 edac_unregister_sysfs_edac_name();
249 * module exit/termination function
251 static void __exit edac_exit(void)
253 debugf0("%s()\n", __func__);
254 kthread_stop(edac_thread);
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();
264 * Inform the kernel of our entry and exit points
266 module_init(edac_init);
267 module_exit(edac_exit);
269 MODULE_LICENSE("GPL");
270 MODULE_AUTHOR("Doug Thompson www.softwarebitmaker.com, et al");
271 MODULE_DESCRIPTION("Core library routines for EDAC reporting");
273 /* refer to *_sysfs.c files for parameters that are exported via sysfs */
275 #ifdef CONFIG_EDAC_DEBUG
276 module_param(edac_debug_level, int, 0644);
277 MODULE_PARM_DESC(edac_debug_level, "Debug level");