1/* 2 * common EDAC components that must be in kernel 3 * 4 * Author: Dave Jiang <djiang@mvista.com> 5 * 6 * 2007 (c) MontaVista Software, Inc. 7 * 2010 (c) Advanced Micro Devices Inc. 8 * Borislav Petkov <bp@alien8.de> 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. 13 * 14 */ 15#include <linux/module.h> 16#include <linux/edac.h> 17#include <linux/atomic.h> 18#include <linux/device.h> 19#include <asm/edac.h> 20 21int edac_op_state = EDAC_OPSTATE_INVAL; 22EXPORT_SYMBOL_GPL(edac_op_state); 23 24atomic_t edac_handlers = ATOMIC_INIT(0); 25EXPORT_SYMBOL_GPL(edac_handlers); 26 27int edac_err_assert = 0; 28EXPORT_SYMBOL_GPL(edac_err_assert); 29 30static atomic_t edac_subsys_valid = ATOMIC_INIT(0); 31 32int edac_report_status = EDAC_REPORTING_ENABLED; 33EXPORT_SYMBOL_GPL(edac_report_status); 34 35static int __init edac_report_setup(char *str) 36{ 37 if (!str) 38 return -EINVAL; 39 40 if (!strncmp(str, "on", 2)) 41 set_edac_report_status(EDAC_REPORTING_ENABLED); 42 else if (!strncmp(str, "off", 3)) 43 set_edac_report_status(EDAC_REPORTING_DISABLED); 44 else if (!strncmp(str, "force", 5)) 45 set_edac_report_status(EDAC_REPORTING_FORCE); 46 47 return 0; 48} 49__setup("edac_report=", edac_report_setup); 50 51/* 52 * called to determine if there is an EDAC driver interested in 53 * knowing an event (such as NMI) occurred 54 */ 55int edac_handler_set(void) 56{ 57 if (edac_op_state == EDAC_OPSTATE_POLL) 58 return 0; 59 60 return atomic_read(&edac_handlers); 61} 62EXPORT_SYMBOL_GPL(edac_handler_set); 63 64/* 65 * handler for NMI type of interrupts to assert error 66 */ 67void edac_atomic_assert_error(void) 68{ 69 edac_err_assert++; 70} 71EXPORT_SYMBOL_GPL(edac_atomic_assert_error); 72 73/* 74 * sysfs object: /sys/devices/system/edac 75 * need to export to other files 76 */ 77struct bus_type edac_subsys = { 78 .name = "edac", 79 .dev_name = "edac", 80}; 81EXPORT_SYMBOL_GPL(edac_subsys); 82 83/* return pointer to the 'edac' node in sysfs */ 84struct bus_type *edac_get_sysfs_subsys(void) 85{ 86 int err = 0; 87 88 if (atomic_read(&edac_subsys_valid)) 89 goto out; 90 91 /* create the /sys/devices/system/edac directory */ 92 err = subsys_system_register(&edac_subsys, NULL); 93 if (err) { 94 printk(KERN_ERR "Error registering toplevel EDAC sysfs dir\n"); 95 return NULL; 96 } 97 98out: 99 atomic_inc(&edac_subsys_valid); 100 return &edac_subsys; 101} 102EXPORT_SYMBOL_GPL(edac_get_sysfs_subsys); 103 104void edac_put_sysfs_subsys(void) 105{ 106 /* last user unregisters it */ 107 if (atomic_dec_and_test(&edac_subsys_valid)) 108 bus_unregister(&edac_subsys); 109} 110EXPORT_SYMBOL_GPL(edac_put_sysfs_subsys); 111