| 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 <[email protected]>
|
| 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(buf, 0, &val);
|
| 29 | if (ret)
|
| 30 | return ret;
|
| 31 |
|
| 32 | if (val > 4)
|
| 33 | return -EINVAL;
|
| 34 |
|
| 35 | return param_set_int(buf, kp);
|
| 36 | }
|
| 37 |
|
| 38 |
|
| 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 |
|
| 80 | err = subsys_system_register(&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(&edac_subsys);
|
| 90 | }
|
| 91 |
|
| 92 |
|
| 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 |
|
| 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");
|