]>
git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - drivers/edac/edac_module.c
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.4 " __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");