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