xref: /openbmc/linux/drivers/edac/edac_module.c (revision c21b37f6)
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: 2.1.0 " __DATE__
19 
20 #ifdef CONFIG_EDAC_DEBUG
21 /* Values of 0 to 4 will generate output */
22 int edac_debug_level = 2;
23 EXPORT_SYMBOL_GPL(edac_debug_level);
24 #endif
25 
26 /* scope is to module level only */
27 struct workqueue_struct *edac_workqueue;
28 
29 /*
30  * sysfs object: /sys/devices/system/edac
31  *	need to export to other files in this modules
32  */
33 static struct sysdev_class edac_class = {
34 	set_kset_name("edac"),
35 };
36 static int edac_class_valid;
37 
38 /*
39  * edac_op_state_to_string()
40  */
41 char *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  * edac_get_edac_class()
59  *
60  *	return pointer to the edac class of 'edac'
61  */
62 struct 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  * edac_register_sysfs_edac_name()
74  *
75  *	register the 'edac' into /sys/devices/system
76  *
77  * return:
78  *	0  success
79  *	!0 error
80  */
81 static int edac_register_sysfs_edac_name(void)
82 {
83 	int err;
84 
85 	/* create the /sys/devices/system/edac directory */
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  * sysdev_class_unregister()
99  *
100  *	unregister the 'edac' from /sys/devices/system
101  */
102 static void edac_unregister_sysfs_edac_name(void)
103 {
104 	/* only if currently registered, then unregister it */
105 	if (edac_class_valid)
106 		sysdev_class_unregister(&edac_class);
107 
108 	edac_class_valid = 0;
109 }
110 
111 /*
112  * edac_workqueue_setup
113  *	initialize the edac work queue for polling operations
114  */
115 static 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  * edac_workqueue_teardown
126  *	teardown the edac workqueue
127  */
128 static 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  * edac_init
139  *      module initialization entry point
140  */
141 static int __init edac_init(void)
142 {
143 	int err = 0;
144 
145 	edac_printk(KERN_INFO, EDAC_MC, EDAC_VERSION "\n");
146 
147 	/*
148 	 * Harvest and clear any boot/initialization PCI parity errors
149 	 *
150 	 * FIXME: This only clears errors logged by devices present at time of
151 	 *      module initialization.  We should also do an initial clear
152 	 *      of each newly hotplugged device.
153 	 */
154 	edac_pci_clear_parity_errors();
155 
156 	/*
157 	 * perform the registration of the /sys/devices/system/edac class object
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 	 * now set up the mc_kset under the edac class object
168 	 */
169 	err = edac_sysfs_setup_mc_kset();
170 	if (err)
171 		goto sysfs_setup_fail;
172 
173 	/* Setup/Initialize the workq for this core */
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 	/* Error teardown stack */
183 workq_fail:
184 	edac_sysfs_teardown_mc_kset();
185 
186 sysfs_setup_fail:
187 	edac_unregister_sysfs_edac_name();
188 
189 error:
190 	return err;
191 }
192 
193 /*
194  * edac_exit()
195  *      module exit/termination function
196  */
197 static void __exit edac_exit(void)
198 {
199 	debugf0("%s()\n", __func__);
200 
201 	/* tear down the various subsystems */
202 	edac_workqueue_teardown();
203 	edac_sysfs_teardown_mc_kset();
204 	edac_unregister_sysfs_edac_name();
205 }
206 
207 /*
208  * Inform the kernel of our entry and exit points
209  */
210 module_init(edac_init);
211 module_exit(edac_exit);
212 
213 MODULE_LICENSE("GPL");
214 MODULE_AUTHOR("Doug Thompson www.softwarebitmaker.com, et al");
215 MODULE_DESCRIPTION("Core library routines for EDAC reporting");
216 
217 /* refer to *_sysfs.c files for parameters that are exported via sysfs */
218 
219 #ifdef CONFIG_EDAC_DEBUG
220 module_param(edac_debug_level, int, 0644);
221 MODULE_PARM_DESC(edac_debug_level, "Debug level");
222 #endif
223