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