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_mc.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, |
23 | const struct kernel_param *kp) |
24 | { |
25 | unsigned long val; |
26 | int ret; |
27 | |
28 | ret = kstrtoul(s: buf, base: 0, res: &val); |
29 | if (ret) |
30 | return ret; |
31 | |
32 | if (val > 4) |
33 | return -EINVAL; |
34 | |
35 | return param_set_int(val: buf, kp); |
36 | } |
37 | |
38 | /* Values of 0 to 4 will generate output */ |
39 | int edac_debug_level = 2; |
40 | EXPORT_SYMBOL_GPL(edac_debug_level); |
41 | |
42 | module_param_call(edac_debug_level, edac_set_debug_level, param_get_int, |
43 | &edac_debug_level, 0644); |
44 | MODULE_PARM_DESC(edac_debug_level, "EDAC debug level: [0-4], default: 2" ); |
45 | #endif |
46 | |
47 | /* |
48 | * edac_op_state_to_string() |
49 | */ |
50 | char *edac_op_state_to_string(int opstate) |
51 | { |
52 | if (opstate == OP_RUNNING_POLL) |
53 | return "POLLED" ; |
54 | else if (opstate == OP_RUNNING_INTERRUPT) |
55 | return "INTERRUPT" ; |
56 | else if (opstate == OP_RUNNING_POLL_INTR) |
57 | return "POLL-INTR" ; |
58 | else if (opstate == OP_ALLOC) |
59 | return "ALLOC" ; |
60 | else if (opstate == OP_OFFLINE) |
61 | return "OFFLINE" ; |
62 | |
63 | return "UNKNOWN" ; |
64 | } |
65 | |
66 | /* |
67 | * sysfs object: /sys/devices/system/edac |
68 | * need to export to other files |
69 | */ |
70 | static const struct bus_type edac_subsys = { |
71 | .name = "edac" , |
72 | .dev_name = "edac" , |
73 | }; |
74 | |
75 | static int edac_subsys_init(void) |
76 | { |
77 | int err; |
78 | |
79 | /* create the /sys/devices/system/edac directory */ |
80 | err = subsys_system_register(subsys: &edac_subsys, NULL); |
81 | if (err) |
82 | printk(KERN_ERR "Error registering toplevel EDAC sysfs dir\n" ); |
83 | |
84 | return err; |
85 | } |
86 | |
87 | static void edac_subsys_exit(void) |
88 | { |
89 | bus_unregister(bus: &edac_subsys); |
90 | } |
91 | |
92 | /* return pointer to the 'edac' node in sysfs */ |
93 | const struct bus_type *edac_get_sysfs_subsys(void) |
94 | { |
95 | return &edac_subsys; |
96 | } |
97 | EXPORT_SYMBOL_GPL(edac_get_sysfs_subsys); |
98 | /* |
99 | * edac_init |
100 | * module initialization entry point |
101 | */ |
102 | static int __init edac_init(void) |
103 | { |
104 | int err = 0; |
105 | |
106 | edac_printk(KERN_INFO, EDAC_MC, EDAC_VERSION "\n" ); |
107 | |
108 | err = edac_subsys_init(); |
109 | if (err) |
110 | return err; |
111 | |
112 | /* |
113 | * Harvest and clear any boot/initialization PCI parity errors |
114 | * |
115 | * FIXME: This only clears errors logged by devices present at time of |
116 | * module initialization. We should also do an initial clear |
117 | * of each newly hotplugged device. |
118 | */ |
119 | edac_pci_clear_parity_errors(); |
120 | |
121 | err = edac_mc_sysfs_init(); |
122 | if (err) |
123 | goto err_sysfs; |
124 | |
125 | edac_debugfs_init(); |
126 | |
127 | err = edac_workqueue_setup(); |
128 | if (err) { |
129 | edac_printk(KERN_ERR, EDAC_MC, "Failure initializing workqueue\n" ); |
130 | goto err_wq; |
131 | } |
132 | |
133 | return 0; |
134 | |
135 | err_wq: |
136 | edac_debugfs_exit(); |
137 | edac_mc_sysfs_exit(); |
138 | |
139 | err_sysfs: |
140 | edac_subsys_exit(); |
141 | |
142 | return err; |
143 | } |
144 | |
145 | /* |
146 | * edac_exit() |
147 | * module exit/termination function |
148 | */ |
149 | static void __exit edac_exit(void) |
150 | { |
151 | edac_dbg(0, "\n" ); |
152 | |
153 | /* tear down the various subsystems */ |
154 | edac_workqueue_teardown(); |
155 | edac_mc_sysfs_exit(); |
156 | edac_debugfs_exit(); |
157 | edac_subsys_exit(); |
158 | } |
159 | |
160 | /* |
161 | * Inform the kernel of our entry and exit points |
162 | */ |
163 | subsys_initcall(edac_init); |
164 | module_exit(edac_exit); |
165 | |
166 | MODULE_LICENSE("GPL" ); |
167 | MODULE_AUTHOR("Doug Thompson www.softwarebitmaker.com, et al" ); |
168 | MODULE_DESCRIPTION("Core library routines for EDAC reporting" ); |
169 | |