Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

EDAC: Export edac sysfs class to users.

Move toplevel sysfs class to the stub and make it available to
non-modularized code too. Add proper refcounting of its users and move
the registration functionality into the reference counting routines.

Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>

authored by

Borislav Petkov and committed by
Borislav Petkov
30e1f7a8 7cfd4a87

+75 -95
+10 -6
drivers/edac/edac_device_sysfs.c
··· 13 13 #include <linux/ctype.h> 14 14 #include <linux/module.h> 15 15 #include <linux/slab.h> 16 + #include <linux/edac.h> 16 17 17 18 #include "edac_core.h" 18 19 #include "edac_module.h" ··· 236 235 debugf1("%s()\n", __func__); 237 236 238 237 /* get the /sys/devices/system/edac reference */ 239 - edac_class = edac_get_edac_class(); 238 + edac_class = edac_get_sysfs_class(); 240 239 if (edac_class == NULL) { 241 240 debugf1("%s() no edac_class error\n", __func__); 242 241 err = -ENODEV; ··· 256 255 257 256 if (!try_module_get(edac_dev->owner)) { 258 257 err = -ENODEV; 259 - goto err_out; 258 + goto err_mod_get; 260 259 } 261 260 262 261 /* register */ ··· 283 282 err_kobj_reg: 284 283 module_put(edac_dev->owner); 285 284 285 + err_mod_get: 286 + edac_put_sysfs_class(); 287 + 286 288 err_out: 287 289 return err; 288 290 } ··· 294 290 * edac_device_unregister_sysfs_main_kobj: 295 291 * the '..../edac/<name>' kobject 296 292 */ 297 - void edac_device_unregister_sysfs_main_kobj( 298 - struct edac_device_ctl_info *edac_dev) 293 + void edac_device_unregister_sysfs_main_kobj(struct edac_device_ctl_info *dev) 299 294 { 300 295 debugf0("%s()\n", __func__); 301 296 debugf4("%s() name of kobject is: %s\n", 302 - __func__, kobject_name(&edac_dev->kobj)); 297 + __func__, kobject_name(&dev->kobj)); 303 298 304 299 /* 305 300 * Unregister the edac device's kobject and ··· 307 304 * a) module_put() this module 308 305 * b) 'kfree' the memory 309 306 */ 310 - kobject_put(&edac_dev->kobj); 307 + kobject_put(&dev->kobj); 308 + edac_put_sysfs_class(); 311 309 } 312 310 313 311 /* edac_dev -> instance information */
+6 -3
drivers/edac/edac_mc_sysfs.c
··· 11 11 12 12 #include <linux/ctype.h> 13 13 #include <linux/slab.h> 14 + #include <linux/edac.h> 14 15 #include <linux/bug.h> 15 16 16 17 #include "edac_core.h" ··· 1018 1017 debugf1("%s()\n", __func__); 1019 1018 1020 1019 /* get the /sys/devices/system/edac class reference */ 1021 - edac_class = edac_get_edac_class(); 1020 + edac_class = edac_get_sysfs_class(); 1022 1021 if (edac_class == NULL) { 1023 1022 debugf1("%s() no edac_class error=%d\n", __func__, err); 1024 1023 goto fail_out; ··· 1029 1028 if (!mc_kset) { 1030 1029 err = -ENOMEM; 1031 1030 debugf1("%s() Failed to register '.../edac/mc'\n", __func__); 1032 - goto fail_out; 1031 + goto fail_kset; 1033 1032 } 1034 1033 1035 1034 debugf1("%s() Registered '.../edac/mc' kobject\n", __func__); 1036 1035 1037 1036 return 0; 1038 1037 1038 + fail_kset: 1039 + edac_put_sysfs_class(); 1039 1040 1040 - /* error unwind stack */ 1041 1041 fail_out: 1042 1042 return err; 1043 1043 } ··· 1051 1049 void edac_sysfs_teardown_mc_kset(void) 1052 1050 { 1053 1051 kset_unregister(mc_kset); 1052 + edac_put_sysfs_class(); 1054 1053 } 1055 1054
+1 -78
drivers/edac/edac_module.c
··· 27 27 struct workqueue_struct *edac_workqueue; 28 28 29 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 30 * edac_op_state_to_string() 40 31 */ 41 32 char *edac_op_state_to_string(int opstate) ··· 43 52 return "OFFLINE"; 44 53 45 54 return "UNKNOWN"; 46 - } 47 - 48 - /* 49 - * edac_get_edac_class() 50 - * 51 - * return pointer to the edac class of 'edac' 52 - */ 53 - struct sysdev_class *edac_get_edac_class(void) 54 - { 55 - struct sysdev_class *classptr = NULL; 56 - 57 - if (edac_class_valid) 58 - classptr = &edac_class; 59 - 60 - return classptr; 61 - } 62 - 63 - /* 64 - * edac_register_sysfs_edac_name() 65 - * 66 - * register the 'edac' into /sys/devices/system 67 - * 68 - * return: 69 - * 0 success 70 - * !0 error 71 - */ 72 - static int edac_register_sysfs_edac_name(void) 73 - { 74 - int err; 75 - 76 - /* create the /sys/devices/system/edac directory */ 77 - err = sysdev_class_register(&edac_class); 78 - 79 - if (err) { 80 - debugf1("%s() error=%d\n", __func__, err); 81 - return err; 82 - } 83 - 84 - edac_class_valid = 1; 85 - return 0; 86 - } 87 - 88 - /* 89 - * sysdev_class_unregister() 90 - * 91 - * unregister the 'edac' from /sys/devices/system 92 - */ 93 - static void edac_unregister_sysfs_edac_name(void) 94 - { 95 - /* only if currently registered, then unregister it */ 96 - if (edac_class_valid) 97 - sysdev_class_unregister(&edac_class); 98 - 99 - edac_class_valid = 0; 100 55 } 101 56 102 57 /* ··· 91 154 edac_pci_clear_parity_errors(); 92 155 93 156 /* 94 - * perform the registration of the /sys/devices/system/edac class object 95 - */ 96 - if (edac_register_sysfs_edac_name()) { 97 - edac_printk(KERN_ERR, EDAC_MC, 98 - "Error initializing 'edac' kobject\n"); 99 - err = -ENODEV; 100 - goto error; 101 - } 102 - 103 - /* 104 157 * now set up the mc_kset under the edac class object 105 158 */ 106 159 err = edac_sysfs_setup_mc_kset(); 107 160 if (err) 108 - goto sysfs_setup_fail; 161 + goto error; 109 162 110 163 /* Setup/Initialize the workq for this core */ 111 164 err = edac_workqueue_setup(); ··· 109 182 /* Error teardown stack */ 110 183 workq_fail: 111 184 edac_sysfs_teardown_mc_kset(); 112 - 113 - sysfs_setup_fail: 114 - edac_unregister_sysfs_edac_name(); 115 185 116 186 error: 117 187 return err; ··· 125 201 /* tear down the various subsystems */ 126 202 edac_workqueue_teardown(); 127 203 edac_sysfs_teardown_mc_kset(); 128 - edac_unregister_sysfs_edac_name(); 129 204 } 130 205 131 206 /*
-1
drivers/edac/edac_module.h
··· 42 42 struct edac_device_ctl_info *edac_dev); 43 43 extern int edac_device_create_sysfs(struct edac_device_ctl_info *edac_dev); 44 44 extern void edac_device_remove_sysfs(struct edac_device_ctl_info *edac_dev); 45 - extern struct sysdev_class *edac_get_edac_class(void); 46 45 47 46 /* edac core workqueue: single CPU mode */ 48 47 extern struct workqueue_struct *edac_workqueue;
+7 -3
drivers/edac/edac_pci_sysfs.c
··· 7 7 * 8 8 */ 9 9 #include <linux/module.h> 10 - #include <linux/sysdev.h> 10 + #include <linux/edac.h> 11 11 #include <linux/slab.h> 12 12 #include <linux/ctype.h> 13 13 ··· 354 354 /* First time, so create the main kobject and its 355 355 * controls and atributes 356 356 */ 357 - edac_class = edac_get_edac_class(); 357 + edac_class = edac_get_sysfs_class(); 358 358 if (edac_class == NULL) { 359 359 debugf1("%s() no edac_class\n", __func__); 360 360 err = -ENODEV; ··· 368 368 if (!try_module_get(THIS_MODULE)) { 369 369 debugf1("%s() try_module_get() failed\n", __func__); 370 370 err = -ENODEV; 371 - goto decrement_count_fail; 371 + goto mod_get_fail; 372 372 } 373 373 374 374 edac_pci_top_main_kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL); ··· 403 403 kzalloc_fail: 404 404 module_put(THIS_MODULE); 405 405 406 + mod_get_fail: 407 + edac_put_sysfs_class(); 408 + 406 409 decrement_count_fail: 407 410 /* if are on this error exit, nothing to tear down */ 408 411 atomic_dec(&edac_pci_sysfs_refcount); ··· 432 429 __func__); 433 430 kobject_put(edac_pci_top_main_kobj); 434 431 } 432 + edac_put_sysfs_class(); 435 433 } 436 434 437 435 /*
+47 -4
drivers/edac/edac_stub.c
··· 3 3 * 4 4 * Author: Dave Jiang <djiang@mvista.com> 5 5 * 6 - * 2007 (c) MontaVista Software, Inc. This file is licensed under 7 - * the terms of the GNU General Public License version 2. This program 8 - * is licensed "as is" without any warranty of any kind, whether express 9 - * or implied. 6 + * 2007 (c) MontaVista Software, Inc. 7 + * 2010 (c) Advanced Micro Devices Inc. 8 + * Borislav Petkov <borislav.petkov@amd.com> 9 + * 10 + * This file is licensed under the terms of the GNU General Public 11 + * License version 2. This program is licensed "as is" without any 12 + * warranty of any kind, whether express or implied. 10 13 * 11 14 */ 12 15 #include <linux/module.h> ··· 25 22 26 23 int edac_err_assert = 0; 27 24 EXPORT_SYMBOL_GPL(edac_err_assert); 25 + 26 + static atomic_t edac_class_valid = ATOMIC_INIT(0); 28 27 29 28 /* 30 29 * called to determine if there is an EDAC driver interested in ··· 49 44 edac_err_assert++; 50 45 } 51 46 EXPORT_SYMBOL_GPL(edac_atomic_assert_error); 47 + 48 + /* 49 + * sysfs object: /sys/devices/system/edac 50 + * need to export to other files 51 + */ 52 + struct sysdev_class edac_class = { 53 + .name = "edac", 54 + }; 55 + EXPORT_SYMBOL_GPL(edac_class); 56 + 57 + /* return pointer to the 'edac' node in sysfs */ 58 + struct sysdev_class *edac_get_sysfs_class(void) 59 + { 60 + int err = 0; 61 + 62 + if (atomic_read(&edac_class_valid)) 63 + goto out; 64 + 65 + /* create the /sys/devices/system/edac directory */ 66 + err = sysdev_class_register(&edac_class); 67 + if (err) { 68 + printk(KERN_ERR "Error registering toplevel EDAC sysfs dir\n"); 69 + return NULL; 70 + } 71 + 72 + out: 73 + atomic_inc(&edac_class_valid); 74 + return &edac_class; 75 + } 76 + EXPORT_SYMBOL_GPL(edac_get_sysfs_class); 77 + 78 + void edac_put_sysfs_class(void) 79 + { 80 + /* last user unregisters it */ 81 + if (atomic_dec_and_test(&edac_class_valid)) 82 + sysdev_class_unregister(&edac_class); 83 + } 84 + EXPORT_SYMBOL_GPL(edac_put_sysfs_class);
+4
include/linux/edac.h
··· 13 13 #define _LINUX_EDAC_H_ 14 14 15 15 #include <asm/atomic.h> 16 + #include <linux/sysdev.h> 16 17 17 18 #define EDAC_OPSTATE_INVAL -1 18 19 #define EDAC_OPSTATE_POLL 0 ··· 23 22 extern int edac_op_state; 24 23 extern int edac_err_assert; 25 24 extern atomic_t edac_handlers; 25 + extern struct sysdev_class edac_class; 26 26 27 27 extern int edac_handler_set(void); 28 28 extern void edac_atomic_assert_error(void); 29 + extern struct sysdev_class *edac_get_sysfs_class(void); 30 + extern void edac_put_sysfs_class(void); 29 31 30 32 static inline void opstate_init(void) 31 33 {