2007-07-19 01:49:46 -07:00
/*
* common EDAC components that must be in kernel
*
* Author : Dave Jiang < djiang @ mvista . com >
*
2010-09-02 17:26:48 +02:00
* 2007 ( c ) MontaVista Software , Inc .
* 2010 ( c ) Advanced Micro Devices Inc .
2012-10-29 18:40:09 +01:00
* Borislav Petkov < bp @ alien8 . de >
2010-09-02 17:26:48 +02:00
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed " as is " without any
* warranty of any kind , whether express or implied .
2007-07-19 01:49:46 -07:00
*
*/
# include <linux/module.h>
# include <linux/edac.h>
2011-07-26 16:09:06 -07:00
# include <linux/atomic.h>
2012-01-22 11:23:42 -05:00
# include <linux/device.h>
2007-07-19 01:49:46 -07:00
int edac_op_state = EDAC_OPSTATE_INVAL ;
2007-07-19 01:50:30 -07:00
EXPORT_SYMBOL_GPL ( edac_op_state ) ;
2007-07-19 01:49:46 -07:00
atomic_t edac_handlers = ATOMIC_INIT ( 0 ) ;
2007-07-19 01:50:30 -07:00
EXPORT_SYMBOL_GPL ( edac_handlers ) ;
2007-07-19 01:49:46 -07:00
2007-07-19 01:49:54 -07:00
int edac_err_assert = 0 ;
2007-07-19 01:50:30 -07:00
EXPORT_SYMBOL_GPL ( edac_err_assert ) ;
2007-07-19 01:49:46 -07:00
2011-12-14 15:21:07 -08:00
static atomic_t edac_subsys_valid = ATOMIC_INIT ( 0 ) ;
2010-09-02 17:26:48 +02:00
2013-12-06 01:17:08 -05:00
int edac_report_status = EDAC_REPORTING_ENABLED ;
EXPORT_SYMBOL_GPL ( edac_report_status ) ;
static int __init edac_report_setup ( char * str )
{
if ( ! str )
return - EINVAL ;
if ( ! strncmp ( str , " on " , 2 ) )
set_edac_report_status ( EDAC_REPORTING_ENABLED ) ;
else if ( ! strncmp ( str , " off " , 3 ) )
set_edac_report_status ( EDAC_REPORTING_DISABLED ) ;
else if ( ! strncmp ( str , " force " , 5 ) )
set_edac_report_status ( EDAC_REPORTING_FORCE ) ;
return 0 ;
}
__setup ( " edac_report= " , edac_report_setup ) ;
2007-07-19 01:50:30 -07:00
/*
* called to determine if there is an EDAC driver interested in
* knowing an event ( such as NMI ) occurred
*/
int edac_handler_set ( void )
2007-07-19 01:49:46 -07:00
{
if ( edac_op_state = = EDAC_OPSTATE_POLL )
return 0 ;
return atomic_read ( & edac_handlers ) ;
}
2007-07-19 01:50:30 -07:00
EXPORT_SYMBOL_GPL ( edac_handler_set ) ;
2007-07-19 01:49:46 -07:00
/*
* handler for NMI type of interrupts to assert error
*/
2007-07-19 01:50:30 -07:00
void edac_atomic_assert_error ( void )
2007-07-19 01:49:46 -07:00
{
2007-07-19 01:49:54 -07:00
edac_err_assert + + ;
2007-07-19 01:49:46 -07:00
}
2007-07-19 01:50:30 -07:00
EXPORT_SYMBOL_GPL ( edac_atomic_assert_error ) ;
2010-09-02 17:26:48 +02:00
/*
* sysfs object : / sys / devices / system / edac
* need to export to other files
*/
2011-12-14 15:21:07 -08:00
struct bus_type edac_subsys = {
2010-09-02 17:26:48 +02:00
. name = " edac " ,
2011-12-14 15:21:07 -08:00
. dev_name = " edac " ,
2010-09-02 17:26:48 +02:00
} ;
2011-12-14 15:21:07 -08:00
EXPORT_SYMBOL_GPL ( edac_subsys ) ;
2010-09-02 17:26:48 +02:00
/* return pointer to the 'edac' node in sysfs */
2011-12-14 15:21:07 -08:00
struct bus_type * edac_get_sysfs_subsys ( void )
2010-09-02 17:26:48 +02:00
{
int err = 0 ;
2011-12-14 15:21:07 -08:00
if ( atomic_read ( & edac_subsys_valid ) )
2010-09-02 17:26:48 +02:00
goto out ;
/* create the /sys/devices/system/edac directory */
2011-12-14 15:21:07 -08:00
err = subsys_system_register ( & edac_subsys , NULL ) ;
2010-09-02 17:26:48 +02:00
if ( err ) {
printk ( KERN_ERR " Error registering toplevel EDAC sysfs dir \n " ) ;
return NULL ;
}
out :
2011-12-14 15:21:07 -08:00
atomic_inc ( & edac_subsys_valid ) ;
return & edac_subsys ;
2010-09-02 17:26:48 +02:00
}
2011-12-14 15:21:07 -08:00
EXPORT_SYMBOL_GPL ( edac_get_sysfs_subsys ) ;
2010-09-02 17:26:48 +02:00
2011-12-14 15:21:07 -08:00
void edac_put_sysfs_subsys ( void )
2010-09-02 17:26:48 +02:00
{
/* last user unregisters it */
2011-12-14 15:21:07 -08:00
if ( atomic_dec_and_test ( & edac_subsys_valid ) )
bus_unregister ( & edac_subsys ) ;
2010-09-02 17:26:48 +02:00
}
2011-12-14 15:21:07 -08:00
EXPORT_SYMBOL_GPL ( edac_put_sysfs_subsys ) ;