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