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: 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        /*
 148         * Harvest and clear any boot/initialization PCI parity errors
 149         *
 150         * FIXME: This only clears errors logged by devices present at time of
 151         *      module initialization.  We should also do an initial clear
 152         *      of each newly hotplugged device.
 153         */
 154        edac_pci_clear_parity_errors();
 155
 156        /*
 157         * perform the registration of the /sys/devices/system/edac class object
 158         */
 159        if (edac_register_sysfs_edac_name()) {
 160                edac_printk(KERN_ERR, EDAC_MC,
 161                        "Error initializing 'edac' kobject\n");
 162                err = -ENODEV;
 163                goto error;
 164        }
 165
 166        /*
 167         * now set up the mc_kset under the edac class object
 168         */
 169        err = edac_sysfs_setup_mc_kset();
 170        if (err)
 171                goto sysfs_setup_fail;
 172
 173        /* Setup/Initialize the workq for this core */
 174        err = edac_workqueue_setup();
 175        if (err) {
 176                edac_printk(KERN_ERR, EDAC_MC, "init WorkQueue failure\n");
 177                goto workq_fail;
 178        }
 179
 180        return 0;
 181
 182        /* Error teardown stack */
 183workq_fail:
 184        edac_sysfs_teardown_mc_kset();
 185
 186sysfs_setup_fail:
 187        edac_unregister_sysfs_edac_name();
 188
 189error:
 190        return err;
 191}
 192
 193/*
 194 * edac_exit()
 195 *      module exit/termination function
 196 */
 197static void __exit edac_exit(void)
 198{
 199        debugf0("%s()\n", __func__);
 200
 201        /* tear down the various subsystems */
 202        edac_workqueue_teardown();
 203        edac_sysfs_teardown_mc_kset();
 204        edac_unregister_sysfs_edac_name();
 205}
 206
 207/*
 208 * Inform the kernel of our entry and exit points
 209 */
 210module_init(edac_init);
 211module_exit(edac_exit);
 212
 213MODULE_LICENSE("GPL");
 214MODULE_AUTHOR("Doug Thompson www.softwarebitmaker.com, et al");
 215MODULE_DESCRIPTION("Core library routines for EDAC reporting");
 216
 217/* refer to *_sysfs.c files for parameters that are exported via sysfs */
 218
 219#ifdef CONFIG_EDAC_DEBUG
 220module_param(edac_debug_level, int, 0644);
 221MODULE_PARM_DESC(edac_debug_level, "Debug level");
 222#endif
 223