1
2
3
4
5
6
7
8
9
10
11
12
13#include <linux/edac.h>
14
15#include "edac_core.h"
16#include "edac_module.h"
17
18#define EDAC_VERSION "Ver: 2.1.0 " __DATE__
19
20#ifdef CONFIG_EDAC_DEBUG
21
22int edac_debug_level = 2;
23EXPORT_SYMBOL_GPL(edac_debug_level);
24#endif
25
26
27struct workqueue_struct *edac_workqueue;
28
29
30
31
32
33static struct sysdev_class edac_class = {
34 .name = "edac",
35};
36static int edac_class_valid;
37
38
39
40
41char *edac_op_state_to_string(int opstate)
42{
43 if (opstate == OP_RUNNING_POLL)
44 return "POLLED";
45 else if (opstate == OP_RUNNING_INTERRUPT)
46 return "INTERRUPT";
47 else if (opstate == OP_RUNNING_POLL_INTR)
48 return "POLL-INTR";
49 else if (opstate == OP_ALLOC)
50 return "ALLOC";
51 else if (opstate == OP_OFFLINE)
52 return "OFFLINE";
53
54 return "UNKNOWN";
55}
56
57
58
59
60
61
62struct sysdev_class *edac_get_edac_class(void)
63{
64 struct sysdev_class *classptr = NULL;
65
66 if (edac_class_valid)
67 classptr = &edac_class;
68
69 return classptr;
70}
71
72
73
74
75
76
77
78
79
80
81static int edac_register_sysfs_edac_name(void)
82{
83 int err;
84
85
86 err = sysdev_class_register(&edac_class);
87
88 if (err) {
89 debugf1("%s() error=%d\n", __func__, err);
90 return err;
91 }
92
93 edac_class_valid = 1;
94 return 0;
95}
96
97
98
99
100
101
102static void edac_unregister_sysfs_edac_name(void)
103{
104
105 if (edac_class_valid)
106 sysdev_class_unregister(&edac_class);
107
108 edac_class_valid = 0;
109}
110
111
112
113
114
115static int edac_workqueue_setup(void)
116{
117 edac_workqueue = create_singlethread_workqueue("edac-poller");
118 if (edac_workqueue == NULL)
119 return -ENODEV;
120 else
121 return 0;
122}
123
124
125
126
127
128static void edac_workqueue_teardown(void)
129{
130 if (edac_workqueue) {
131 flush_workqueue(edac_workqueue);
132 destroy_workqueue(edac_workqueue);
133 edac_workqueue = NULL;
134 }
135}
136
137
138
139
140
141static int __init edac_init(void)
142{
143 int err = 0;
144
145 edac_printk(KERN_INFO, EDAC_MC, EDAC_VERSION "\n");
146
147
148
149
150
151
152
153
154 edac_pci_clear_parity_errors();
155
156
157
158
159 if (edac_register_sysfs_edac_name()) {
160 edac_printk(KERN_ERR, EDAC_MC,
161 "Error initializing 'edac' kobject\n");
162 err = -ENODEV;
163 goto error;
164 }
165
166
167
168
169 err = edac_sysfs_setup_mc_kset();
170 if (err)
171 goto sysfs_setup_fail;
172
173
174 err = edac_workqueue_setup();
175 if (err) {
176 edac_printk(KERN_ERR, EDAC_MC, "init WorkQueue failure\n");
177 goto workq_fail;
178 }
179
180 return 0;
181
182
183workq_fail:
184 edac_sysfs_teardown_mc_kset();
185
186sysfs_setup_fail:
187 edac_unregister_sysfs_edac_name();
188
189error:
190 return err;
191}
192
193
194
195
196
197static void __exit edac_exit(void)
198{
199 debugf0("%s()\n", __func__);
200
201
202 edac_workqueue_teardown();
203 edac_sysfs_teardown_mc_kset();
204 edac_unregister_sysfs_edac_name();
205}
206
207
208
209
210module_init(edac_init);
211module_exit(edac_exit);
212
213MODULE_LICENSE("GPL");
214MODULE_AUTHOR("Doug Thompson www.softwarebitmaker.com, et al");
215MODULE_DESCRIPTION("Core library routines for EDAC reporting");
216
217
218
219#ifdef CONFIG_EDAC_DEBUG
220module_param(edac_debug_level, int, 0644);
221MODULE_PARM_DESC(edac_debug_level, "Debug level");
222#endif
223