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