• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/drivers/edac/
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 */
22int edac_debug_level = 2;
23EXPORT_SYMBOL_GPL(edac_debug_level);
24#endif
25
26/* scope is to module level only */
27struct workqueue_struct *edac_workqueue;
28
29/*
30 * sysfs object: /sys/devices/system/edac
31 *	need to export to other files in this modules
32 */
33static struct sysdev_class edac_class = {
34	.name = "edac",
35};
36static int edac_class_valid;
37
38/*
39 * edac_op_state_to_string()
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 * edac_get_edac_class()
59 *
60 *	return pointer to the edac class of 'edac'
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 * edac_register_sysfs_edac_name()
74 *
75 *	register the 'edac' into /sys/devices/system
76 *
77 * return:
78 *	0  success
79 *	!0 error
80 */
81static 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 */
102static 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 */
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 * edac_workqueue_teardown
126 *	teardown the edac workqueue
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 * edac_init
139 *      module initialization entry point
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	edac_pci_clear_parity_errors();
148
149	/*
150	 * perform the registration of the /sys/devices/system/edac class object
151	 */
152	if (edac_register_sysfs_edac_name()) {
153		edac_printk(KERN_ERR, EDAC_MC,
154			"Error initializing 'edac' kobject\n");
155		err = -ENODEV;
156		goto error;
157	}
158
159	/*
160	 * now set up the mc_kset under the edac class object
161	 */
162	err = edac_sysfs_setup_mc_kset();
163	if (err)
164		goto sysfs_setup_fail;
165
166	/* Setup/Initialize the workq for this core */
167	err = edac_workqueue_setup();
168	if (err) {
169		edac_printk(KERN_ERR, EDAC_MC, "init WorkQueue failure\n");
170		goto workq_fail;
171	}
172
173	return 0;
174
175	/* Error teardown stack */
176workq_fail:
177	edac_sysfs_teardown_mc_kset();
178
179sysfs_setup_fail:
180	edac_unregister_sysfs_edac_name();
181
182error:
183	return err;
184}
185
186/*
187 * edac_exit()
188 *      module exit/termination function
189 */
190static void __exit edac_exit(void)
191{
192	debugf0("%s()\n", __func__);
193
194	/* tear down the various subsystems */
195	edac_workqueue_teardown();
196	edac_sysfs_teardown_mc_kset();
197	edac_unregister_sysfs_edac_name();
198}
199
200/*
201 * Inform the kernel of our entry and exit points
202 */
203module_init(edac_init);
204module_exit(edac_exit);
205
206MODULE_LICENSE("GPL");
207MODULE_AUTHOR("Doug Thompson www.softwarebitmaker.com, et al");
208MODULE_DESCRIPTION("Core library routines for EDAC reporting");
209
210/* refer to *_sysfs.c files for parameters that are exported via sysfs */
211
212#ifdef CONFIG_EDAC_DEBUG
213module_param(edac_debug_level, int, 0644);
214MODULE_PARM_DESC(edac_debug_level, "Debug level");
215#endif
216