diff options
Diffstat (limited to 'drivers/edac/edac_module.c')
-rw-r--r-- | drivers/edac/edac_module.c | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/drivers/edac/edac_module.c b/drivers/edac/edac_module.c new file mode 100644 index 000000000000..8db0471a9476 --- /dev/null +++ b/drivers/edac/edac_module.c | |||
@@ -0,0 +1,130 @@ | |||
1 | |||
2 | #include <linux/freezer.h> | ||
3 | #include <linux/kthread.h> | ||
4 | |||
5 | #include "edac_mc.h" | ||
6 | #include "edac_module.h" | ||
7 | |||
8 | #define EDAC_MC_VERSION "Ver: 2.0.3" __DATE__ | ||
9 | |||
10 | #ifdef CONFIG_EDAC_DEBUG | ||
11 | /* Values of 0 to 4 will generate output */ | ||
12 | int edac_debug_level = 1; | ||
13 | EXPORT_SYMBOL_GPL(edac_debug_level); | ||
14 | #endif | ||
15 | |||
16 | static struct task_struct *edac_thread; | ||
17 | |||
18 | /* | ||
19 | * Check MC status every edac_get_poll_msec(). | ||
20 | * Check PCI status every edac_get_poll_msec() as well. | ||
21 | * | ||
22 | * This where the work gets done for edac. | ||
23 | * | ||
24 | * SMP safe, doesn't use NMI, and auto-rate-limits. | ||
25 | */ | ||
26 | static void do_edac_check(void) | ||
27 | { | ||
28 | debugf3("%s()\n", __func__); | ||
29 | |||
30 | /* perform the poll activities */ | ||
31 | edac_check_mc_devices(); | ||
32 | edac_pci_do_parity_check(); | ||
33 | } | ||
34 | |||
35 | /* | ||
36 | * Action thread for EDAC to perform the POLL operations | ||
37 | */ | ||
38 | static int edac_kernel_thread(void *arg) | ||
39 | { | ||
40 | int msec; | ||
41 | |||
42 | while (!kthread_should_stop()) { | ||
43 | |||
44 | do_edac_check(); | ||
45 | |||
46 | /* goto sleep for the interval */ | ||
47 | msec = (HZ * edac_get_poll_msec()) / 1000; | ||
48 | schedule_timeout_interruptible(msec); | ||
49 | try_to_freeze(); | ||
50 | } | ||
51 | |||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | /* | ||
56 | * edac_init | ||
57 | * module initialization entry point | ||
58 | */ | ||
59 | static int __init edac_init(void) | ||
60 | { | ||
61 | edac_printk(KERN_INFO, EDAC_MC, EDAC_MC_VERSION "\n"); | ||
62 | |||
63 | /* | ||
64 | * Harvest and clear any boot/initialization PCI parity errors | ||
65 | * | ||
66 | * FIXME: This only clears errors logged by devices present at time of | ||
67 | * module initialization. We should also do an initial clear | ||
68 | * of each newly hotplugged device. | ||
69 | */ | ||
70 | edac_pci_clear_parity_errors(); | ||
71 | |||
72 | /* Create the MC sysfs entries */ | ||
73 | if (edac_sysfs_memctrl_setup()) { | ||
74 | edac_printk(KERN_ERR, EDAC_MC, | ||
75 | "Error initializing sysfs code\n"); | ||
76 | return -ENODEV; | ||
77 | } | ||
78 | |||
79 | /* Create the PCI parity sysfs entries */ | ||
80 | if (edac_sysfs_pci_setup()) { | ||
81 | edac_sysfs_memctrl_teardown(); | ||
82 | edac_printk(KERN_ERR, EDAC_MC, | ||
83 | "PCI: Error initializing sysfs code\n"); | ||
84 | return -ENODEV; | ||
85 | } | ||
86 | |||
87 | /* create our kernel thread */ | ||
88 | edac_thread = kthread_run(edac_kernel_thread, NULL, "kedac"); | ||
89 | |||
90 | if (IS_ERR(edac_thread)) { | ||
91 | /* remove the sysfs entries */ | ||
92 | edac_sysfs_memctrl_teardown(); | ||
93 | edac_sysfs_pci_teardown(); | ||
94 | return PTR_ERR(edac_thread); | ||
95 | } | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | /* | ||
101 | * edac_exit() | ||
102 | * module exit/termination function | ||
103 | */ | ||
104 | static void __exit edac_exit(void) | ||
105 | { | ||
106 | debugf0("%s()\n", __func__); | ||
107 | kthread_stop(edac_thread); | ||
108 | |||
109 | /* tear down the sysfs device */ | ||
110 | edac_sysfs_memctrl_teardown(); | ||
111 | edac_sysfs_pci_teardown(); | ||
112 | } | ||
113 | |||
114 | /* | ||
115 | * Inform the kernel of our entry and exit points | ||
116 | */ | ||
117 | module_init(edac_init); | ||
118 | module_exit(edac_exit); | ||
119 | |||
120 | MODULE_LICENSE("GPL"); | ||
121 | MODULE_AUTHOR("Doug Thompson www.softwarebitmaker.com, et al"); | ||
122 | MODULE_DESCRIPTION("Core library routines for EDAC reporting"); | ||
123 | |||
124 | /* refer to *_sysfs.c files for parameters that are exported via sysfs */ | ||
125 | |||
126 | #ifdef CONFIG_EDAC_DEBUG | ||
127 | module_param(edac_debug_level, int, 0644); | ||
128 | MODULE_PARM_DESC(edac_debug_level, "Debug level"); | ||
129 | #endif | ||
130 | |||