Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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 */
 22 int edac_debug_level = 2;
 23 EXPORT_SYMBOL_GPL(edac_debug_level);
 24 #endif
 25 
 26 /* scope is to module level only */
 27 struct workqueue_struct *edac_workqueue;
 28 
 29 /*
 30  * sysfs object: /sys/devices/system/edac
 31  *      need to export to other files in this modules
 32  */
 33 static struct sysdev_class edac_class = {
 34         .name = "edac",
 35 };
 36 static int edac_class_valid;
 37 
 38 /*
 39  * edac_op_state_to_string()
 40  */
 41 char *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  */
 62 struct 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  */
 81 static 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  */
102 static 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  */
115 static 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  */
128 static 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  */
141 static 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 */
183 workq_fail:
184         edac_sysfs_teardown_mc_kset();
185 
186 sysfs_setup_fail:
187         edac_unregister_sysfs_edac_name();
188 
189 error:
190         return err;
191 }
192 
193 /*
194  * edac_exit()
195  *      module exit/termination function
196  */
197 static 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  */
210 module_init(edac_init);
211 module_exit(edac_exit);
212 
213 MODULE_LICENSE("GPL");
214 MODULE_AUTHOR("Doug Thompson www.softwarebitmaker.com, et al");
215 MODULE_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
220 module_param(edac_debug_level, int, 0644);
221 MODULE_PARM_DESC(edac_debug_level, "Debug level");
222 #endif
223 
  This page was automatically generated by the LXR engine.