Merge tag 'asoc-v3.17-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie...
[platform/kernel/linux-exynos.git] / drivers / edac / edac_module.c
1 /*
2  * edac_module.c
3  *
4  * (C) 2007 www.softwarebitmaker.com
5  *
6  * This file is licensed under the terms of the GNU General Public
7  * License version 2. This program is licensed "as is" without any
8  * warranty of any kind, whether express or implied.
9  *
10  * Author: Doug Thompson <dougthompson@xmission.com>
11  *
12  */
13 #include <linux/edac.h>
14
15 #include "edac_core.h"
16 #include "edac_module.h"
17
18 #define EDAC_VERSION "Ver: 3.0.0"
19
20 #ifdef CONFIG_EDAC_DEBUG
21
22 static int edac_set_debug_level(const char *buf, struct kernel_param *kp)
23 {
24         unsigned long val;
25         int ret;
26
27         ret = kstrtoul(buf, 0, &val);
28         if (ret)
29                 return ret;
30
31         if (val > 4)
32                 return -EINVAL;
33
34         return param_set_int(buf, kp);
35 }
36
37 /* Values of 0 to 4 will generate output */
38 int edac_debug_level = 2;
39 EXPORT_SYMBOL_GPL(edac_debug_level);
40
41 module_param_call(edac_debug_level, edac_set_debug_level, param_get_int,
42                   &edac_debug_level, 0644);
43 MODULE_PARM_DESC(edac_debug_level, "EDAC debug level: [0-4], default: 2");
44 #endif
45
46 /* scope is to module level only */
47 struct workqueue_struct *edac_workqueue;
48
49 /*
50  * edac_op_state_to_string()
51  */
52 char *edac_op_state_to_string(int opstate)
53 {
54         if (opstate == OP_RUNNING_POLL)
55                 return "POLLED";
56         else if (opstate == OP_RUNNING_INTERRUPT)
57                 return "INTERRUPT";
58         else if (opstate == OP_RUNNING_POLL_INTR)
59                 return "POLL-INTR";
60         else if (opstate == OP_ALLOC)
61                 return "ALLOC";
62         else if (opstate == OP_OFFLINE)
63                 return "OFFLINE";
64
65         return "UNKNOWN";
66 }
67
68 /*
69  * edac_workqueue_setup
70  *      initialize the edac work queue for polling operations
71  */
72 static int edac_workqueue_setup(void)
73 {
74         edac_workqueue = create_singlethread_workqueue("edac-poller");
75         if (edac_workqueue == NULL)
76                 return -ENODEV;
77         else
78                 return 0;
79 }
80
81 /*
82  * edac_workqueue_teardown
83  *      teardown the edac workqueue
84  */
85 static void edac_workqueue_teardown(void)
86 {
87         if (edac_workqueue) {
88                 flush_workqueue(edac_workqueue);
89                 destroy_workqueue(edac_workqueue);
90                 edac_workqueue = NULL;
91         }
92 }
93
94 /*
95  * edac_init
96  *      module initialization entry point
97  */
98 static int __init edac_init(void)
99 {
100         int err = 0;
101
102         edac_printk(KERN_INFO, EDAC_MC, EDAC_VERSION "\n");
103
104         /*
105          * Harvest and clear any boot/initialization PCI parity errors
106          *
107          * FIXME: This only clears errors logged by devices present at time of
108          *      module initialization.  We should also do an initial clear
109          *      of each newly hotplugged device.
110          */
111         edac_pci_clear_parity_errors();
112
113         err = edac_mc_sysfs_init();
114         if (err)
115                 goto error;
116
117         edac_debugfs_init();
118
119         /* Setup/Initialize the workq for this core */
120         err = edac_workqueue_setup();
121         if (err) {
122                 edac_printk(KERN_ERR, EDAC_MC, "init WorkQueue failure\n");
123                 goto error;
124         }
125
126         return 0;
127
128 error:
129         return err;
130 }
131
132 /*
133  * edac_exit()
134  *      module exit/termination function
135  */
136 static void __exit edac_exit(void)
137 {
138         edac_dbg(0, "\n");
139
140         /* tear down the various subsystems */
141         edac_workqueue_teardown();
142         edac_mc_sysfs_exit();
143         edac_debugfs_exit();
144 }
145
146 /*
147  * Inform the kernel of our entry and exit points
148  */
149 subsys_initcall(edac_init);
150 module_exit(edac_exit);
151
152 MODULE_LICENSE("GPL");
153 MODULE_AUTHOR("Doug Thompson www.softwarebitmaker.com, et al");
154 MODULE_DESCRIPTION("Core library routines for EDAC reporting");