Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * edac_module.c
0003  *
0004  * (C) 2007 www.softwarebitmaker.com
0005  *
0006  * This file is licensed under the terms of the GNU General Public
0007  * License version 2. This program is licensed "as is" without any
0008  * warranty of any kind, whether express or implied.
0009  *
0010  * Author: Doug Thompson <dougthompson@xmission.com>
0011  *
0012  */
0013 #include <linux/edac.h>
0014 
0015 #include "edac_mc.h"
0016 #include "edac_module.h"
0017 
0018 #define EDAC_VERSION "Ver: 3.0.0"
0019 
0020 #ifdef CONFIG_EDAC_DEBUG
0021 
0022 static int edac_set_debug_level(const char *buf,
0023                 const struct kernel_param *kp)
0024 {
0025     unsigned long val;
0026     int ret;
0027 
0028     ret = kstrtoul(buf, 0, &val);
0029     if (ret)
0030         return ret;
0031 
0032     if (val > 4)
0033         return -EINVAL;
0034 
0035     return param_set_int(buf, kp);
0036 }
0037 
0038 /* Values of 0 to 4 will generate output */
0039 int edac_debug_level = 2;
0040 EXPORT_SYMBOL_GPL(edac_debug_level);
0041 
0042 module_param_call(edac_debug_level, edac_set_debug_level, param_get_int,
0043           &edac_debug_level, 0644);
0044 MODULE_PARM_DESC(edac_debug_level, "EDAC debug level: [0-4], default: 2");
0045 #endif
0046 
0047 /*
0048  * edac_op_state_to_string()
0049  */
0050 char *edac_op_state_to_string(int opstate)
0051 {
0052     if (opstate == OP_RUNNING_POLL)
0053         return "POLLED";
0054     else if (opstate == OP_RUNNING_INTERRUPT)
0055         return "INTERRUPT";
0056     else if (opstate == OP_RUNNING_POLL_INTR)
0057         return "POLL-INTR";
0058     else if (opstate == OP_ALLOC)
0059         return "ALLOC";
0060     else if (opstate == OP_OFFLINE)
0061         return "OFFLINE";
0062 
0063     return "UNKNOWN";
0064 }
0065 
0066 /*
0067  * sysfs object: /sys/devices/system/edac
0068  *  need to export to other files
0069  */
0070 static struct bus_type edac_subsys = {
0071     .name = "edac",
0072     .dev_name = "edac",
0073 };
0074 
0075 static int edac_subsys_init(void)
0076 {
0077     int err;
0078 
0079     /* create the /sys/devices/system/edac directory */
0080     err = subsys_system_register(&edac_subsys, NULL);
0081     if (err)
0082         printk(KERN_ERR "Error registering toplevel EDAC sysfs dir\n");
0083 
0084     return err;
0085 }
0086 
0087 static void edac_subsys_exit(void)
0088 {
0089     bus_unregister(&edac_subsys);
0090 }
0091 
0092 /* return pointer to the 'edac' node in sysfs */
0093 struct bus_type *edac_get_sysfs_subsys(void)
0094 {
0095     return &edac_subsys;
0096 }
0097 EXPORT_SYMBOL_GPL(edac_get_sysfs_subsys);
0098 /*
0099  * edac_init
0100  *      module initialization entry point
0101  */
0102 static int __init edac_init(void)
0103 {
0104     int err = 0;
0105 
0106     edac_printk(KERN_INFO, EDAC_MC, EDAC_VERSION "\n");
0107 
0108     err = edac_subsys_init();
0109     if (err)
0110         return err;
0111 
0112     /*
0113      * Harvest and clear any boot/initialization PCI parity errors
0114      *
0115      * FIXME: This only clears errors logged by devices present at time of
0116      *      module initialization.  We should also do an initial clear
0117      *      of each newly hotplugged device.
0118      */
0119     edac_pci_clear_parity_errors();
0120 
0121     err = edac_mc_sysfs_init();
0122     if (err)
0123         goto err_sysfs;
0124 
0125     edac_debugfs_init();
0126 
0127     err = edac_workqueue_setup();
0128     if (err) {
0129         edac_printk(KERN_ERR, EDAC_MC, "Failure initializing workqueue\n");
0130         goto err_wq;
0131     }
0132 
0133     return 0;
0134 
0135 err_wq:
0136     edac_debugfs_exit();
0137     edac_mc_sysfs_exit();
0138 
0139 err_sysfs:
0140     edac_subsys_exit();
0141 
0142     return err;
0143 }
0144 
0145 /*
0146  * edac_exit()
0147  *      module exit/termination function
0148  */
0149 static void __exit edac_exit(void)
0150 {
0151     edac_dbg(0, "\n");
0152 
0153     /* tear down the various subsystems */
0154     edac_workqueue_teardown();
0155     edac_mc_sysfs_exit();
0156     edac_debugfs_exit();
0157     edac_subsys_exit();
0158 }
0159 
0160 /*
0161  * Inform the kernel of our entry and exit points
0162  */
0163 subsys_initcall(edac_init);
0164 module_exit(edac_exit);
0165 
0166 MODULE_LICENSE("GPL");
0167 MODULE_AUTHOR("Doug Thompson www.softwarebitmaker.com, et al");
0168 MODULE_DESCRIPTION("Core library routines for EDAC reporting");