@ -9,20 +9,19 @@
# include <zephyr/shell/shell.h>
# include <zephyr/shell/shell.h>
# include <zephyr/drivers/edac.h>
# include <zephyr/drivers/edac.h>
# include "ibecc.h"
static const struct device * const edac_device = DEVICE_DT_GET_OR_NULL ( DT_CHOSEN ( zephyr_edac ) ) ;
/**
/**
* EDAC Error Injection interface
* EDAC Error Injection interface
*
*
* edac inject add r [ value ] Physical memory address base
* edac inject p aram1 [ value ] Show / Set EDAC injection parameter 1
* edac inject mask [ value ] Physical memory address mask
* edac inject param2 [ value ] Show / Set EDAC injection parameter 2
* edac inject error_type Show / Set EDAC error type
* edac inject error_type Show / Set EDAC error type
* edac inject trigger Trigger injection
* edac inject trigger Trigger injection
*
* *
* edac inject test_default Set default injection parameters
* edac disable_nmi Experimental disable NMI ( X86 only )
*
* edac enable_nmi Experimental enable NMI ( X86 only )
* edac disable_nmi Experimental disable NMI
* edac enable_nmi Experimental enable NMI
*
*
* EDAC Report interface
* EDAC Report interface
*
*
@ -35,7 +34,11 @@
* devmem [ width [ value ] ] Physical memory read / write
* devmem [ width [ value ] ] Physical memory read / write
*/
*/
static void decode_ecc_error ( const struct shell * sh , uint64_t ecc_error )
# ifdef CONFIG_EDAC_IBECC
# include "ibecc.h"
static void decode_ibecc_error ( const struct shell * sh , uint64_t ecc_error )
{
{
uint64_t erradd = ECC_ERROR_ERRADD ( ecc_error ) ;
uint64_t erradd = ECC_ERROR_ERRADD ( ecc_error ) ;
unsigned long errsynd = ECC_ERROR_ERRSYND ( ecc_error ) ;
unsigned long errsynd = ECC_ERROR_ERRSYND ( ecc_error ) ;
@ -56,6 +59,8 @@ static void decode_ecc_error(const struct shell *sh, uint64_t ecc_error)
}
}
}
}
# endif /* CONFIG_EDAC_IBECC */
static int ecc_error_show ( const struct shell * sh , const struct device * dev )
static int ecc_error_show ( const struct shell * sh , const struct device * dev )
{
{
uint64_t error ;
uint64_t error ;
@ -69,9 +74,11 @@ static int ecc_error_show(const struct shell *sh, const struct device *dev)
shell_fprintf ( sh , SHELL_NORMAL , " ECC Error: 0x%llx \n " , error ) ;
shell_fprintf ( sh , SHELL_NORMAL , " ECC Error: 0x%llx \n " , error ) ;
# ifdef CONFIG_EDAC_IBECC
if ( error ! = 0 ) {
if ( error ! = 0 ) {
decode_ecc_error ( sh , error ) ;
decode_ib ecc_error ( sh , error ) ;
}
}
# endif /* CONFIG_EDAC_IBECC */
return 0 ;
return 0 ;
}
}
@ -94,75 +101,57 @@ static int parity_error_show(const struct shell *sh, const struct device *dev)
static int cmd_edac_info ( const struct shell * sh , size_t argc , char * * argv )
static int cmd_edac_info ( const struct shell * sh , size_t argc , char * * argv )
{
{
const struct device * dev ;
if ( ! device_is_ready ( edac_device ) ) {
int err ;
shell_error ( sh , " EDAC device not ready " ) ;
dev = DEVICE_DT_GET ( DT_NODELABEL ( ibecc ) ) ;
if ( ! device_is_ready ( dev ) ) {
shell_error ( sh , " IBECC device not ready " ) ;
return - ENODEV ;
return - ENODEV ;
}
}
shell_fprintf ( sh , SHELL_NORMAL , " Show EDAC status \n " ) ;
shell_fprintf ( sh , SHELL_NORMAL , " Show EDAC status \n " ) ;
err = ecc_error_show ( sh , dev ) ;
( void ) ecc_error_show ( sh , edac_device ) ;
if ( err ! = 0 ) {
return err ;
}
err = parity_error_show ( sh , dev ) ;
( void ) parity_error_show ( sh , edac_device ) ;
if ( err ! = 0 ) {
return err ;
}
shell_fprintf ( sh , SHELL_NORMAL ,
shell_fprintf ( sh , SHELL_NORMAL , " Errors correctable: %d Errors uncorrectable: %d \n " ,
" Errors correctable: %d Errors uncorrectable %d \n " ,
edac_errors_cor_get ( edac_device ) , edac_errors_uc_get ( edac_device ) ) ;
edac_errors_cor_get ( dev ) , edac_errors_uc_get ( dev ) ) ;
return err ;
return 0 ;
}
}
# if defined(CONFIG_EDAC_ERROR_INJECT)
# if defined(CONFIG_EDAC_ERROR_INJECT)
static int cmd_inject_add r ( const struct shell * sh , size_t argc , char * * argv )
static int cmd_inject_p aram1 ( const struct shell * sh , size_t argc , char * * argv )
{
{
const struct device * dev ;
int err ;
int err ;
dev = DEVICE_DT_GET ( DT_NODELABEL ( ibecc ) ) ;
if ( ! device_is_ready ( edac_device ) ) {
if ( ! device_is_ready ( dev ) ) {
shell_error ( sh , " EDAC device not ready " ) ;
shell_error ( sh , " IBECC device not ready " ) ;
return - ENODEV ;
return - ENODEV ;
}
}
if ( argc > 2 ) {
if ( argc > 2 ) {
/* Usage */
/* Usage */
shell_fprintf ( sh , SHELL_NORMAL ,
shell_fprintf ( sh , SHELL_NORMAL , " Usage: edac inject %s [val] \n " , argv [ 0 ] ) ;
" Usage: edac inject %s [addr] \n " , argv [ 0 ] ) ;
return - ENOTSUP ;
return - ENOTSUP ;
}
}
if ( argc = = 1 ) {
if ( argc = = 1 ) {
uint64_t addr ;
uint64_t value ;
err = edac_inject_get_param1 ( dev , & addr ) ;
err = edac_inject_get_param1 ( edac_ device , & value ) ;
if ( err ! = 0 ) {
if ( err ! = 0 ) {
shell_error ( sh , " Error getting address (err %d) " ,
shell_error ( sh , " Error getting param1 (err %d) " , err ) ;
err ) ;
return err ;
return err ;
}
}
shell_fprintf ( sh , SHELL_NORMAL ,
shell_fprintf ( sh , SHELL_NORMAL , " Injection param1: 0x%llx \n " , value ) ;
" Injection address base: 0x%llx \n " , addr ) ;
} else {
} else {
unsigned long value = strtoul ( argv [ 1 ] , NULL , 16 ) ;
unsigned long value = strtoul ( argv [ 1 ] , NULL , 16 ) ;
shell_fprintf ( sh , SHELL_NORMAL ,
shell_fprintf ( sh , SHELL_NORMAL , " Set injection param1 to: %s \n " , argv [ 1 ] ) ;
" Set injection address base to: %s \n " , argv [ 1 ] ) ;
err = edac_inject_set_param1 ( dev , value ) ;
err = edac_inject_set_param1 ( edac_ device , value ) ;
if ( err ! = 0 ) {
if ( err ! = 0 ) {
shell_error ( sh , " Error setting address (err %d) " ,
shell_error ( sh , " Error setting param1 (err %d) " , err ) ;
err ) ;
return err ;
return err ;
}
}
}
}
@ -170,44 +159,39 @@ static int cmd_inject_addr(const struct shell *sh, size_t argc, char **argv)
return err ;
return err ;
}
}
static int cmd_inject_mask ( const struct shell * sh , size_t argc , char * * argv )
static int cmd_inject_param2 ( const struct shell * sh , size_t argc , char * * argv )
{
{
const struct device * dev ;
int err ;
int err ;
dev = DEVICE_DT_GET ( DT_NODELABEL ( ibecc ) ) ;
if ( ! device_is_ready ( edac_device ) ) {
if ( ! device_is_ready ( dev ) ) {
shell_error ( sh , " EDAC device not ready " ) ;
shell_error ( sh , " IBECC device not ready " ) ;
return - ENODEV ;
return - ENODEV ;
}
}
if ( argc > 2 ) {
if ( argc > 2 ) {
/* Usage */
/* Usage */
shell_fprintf ( sh , SHELL_NORMAL ,
shell_fprintf ( sh , SHELL_NORMAL , " Usage: edac inject %s [val] \n " , argv [ 0 ] ) ;
" Usage: edac inject %s [mask] \n " , argv [ 0 ] ) ;
return - ENOTSUP ;
return - ENOTSUP ;
}
}
if ( argc = = 1 ) {
if ( argc = = 1 ) {
uint64_t mask ;
uint64_t value ;
err = edac_inject_get_param2 ( dev , & mask ) ;
err = edac_inject_get_param2 ( edac_ device , & value ) ;
if ( err ! = 0 ) {
if ( err ! = 0 ) {
shell_error ( sh , " Error getting mask (err %d) " , err ) ;
shell_error ( sh , " Error getting param2 (err %d) " , err ) ;
return err ;
return err ;
}
}
shell_fprintf ( sh , SHELL_NORMAL ,
shell_fprintf ( sh , SHELL_NORMAL , " Injection param2: 0x%llx \n " , value ) ;
" Injection address mask: 0x%llx \n " , mask ) ;
} else {
} else {
uint64_t value = strtoul ( argv [ 1 ] , NULL , 16 ) ;
uint64_t value = strtoul ( argv [ 1 ] , NULL , 16 ) ;
shell_fprintf ( sh , SHELL_NORMAL ,
shell_fprintf ( sh , SHELL_NORMAL , " Set injection param2 to %llx \n " , value ) ;
" Set injection address mask to %llx \n " , value ) ;
err = edac_inject_set_param2 ( dev , value ) ;
err = edac_inject_set_param2 ( edac_ device , value ) ;
if ( err ! = 0 ) {
if ( err ! = 0 ) {
shell_error ( sh , " Error setting mask (err %d) " , err ) ;
shell_error ( sh , " Error setting param2 (err %d) " , err ) ;
return err ;
return err ;
}
}
}
}
@ -218,21 +202,20 @@ static int cmd_inject_mask(const struct shell *sh, size_t argc, char **argv)
static int cmd_inject_trigger ( const struct shell * sh , size_t argc ,
static int cmd_inject_trigger ( const struct shell * sh , size_t argc ,
char * * argv )
char * * argv )
{
{
const struct device * dev ;
if ( ! device_is_ready ( edac_device ) ) {
shell_error ( sh , " EDAC device not ready " ) ;
dev = DEVICE_DT_GET ( DT_NODELABEL ( ibecc ) ) ;
if ( ! device_is_ready ( dev ) ) {
shell_error ( sh , " IBECC device not ready " ) ;
return - ENODEV ;
return - ENODEV ;
}
}
shell_fprintf ( sh , SHELL_NORMAL , " Triggering injection \n " ) ;
shell_fprintf ( sh , SHELL_NORMAL , " Triggering injection \n " ) ;
edac_inject_error_trigger ( dev ) ;
edac_inject_error_trigger ( edac_ device ) ;
return 0 ;
return 0 ;
}
}
# ifdef CONFIG_X86
static int cmd_inject_disable_nmi ( const struct shell * sh , size_t argc ,
static int cmd_inject_disable_nmi ( const struct shell * sh , size_t argc ,
char * * argv )
char * * argv )
{
{
@ -249,6 +232,8 @@ static int cmd_inject_enable_nmi(const struct shell *sh, size_t argc,
return 0 ;
return 0 ;
}
}
# endif /* CONFIG_X86 */
static const char * get_error_type ( uint32_t type )
static const char * get_error_type ( uint32_t type )
{
{
switch ( type ) {
switch ( type ) {
@ -264,17 +249,15 @@ static const char *get_error_type(uint32_t type)
static int cmd_inject_error_type_show ( const struct shell * sh , size_t argc ,
static int cmd_inject_error_type_show ( const struct shell * sh , size_t argc ,
char * * argv )
char * * argv )
{
{
const struct device * dev ;
uint32_t error_type ;
uint32_t error_type ;
int err ;
int err ;
dev = DEVICE_DT_GET ( DT_NODELABEL ( ibecc ) ) ;
if ( ! device_is_ready ( edac_device ) ) {
if ( ! device_is_ready ( dev ) ) {
shell_error ( sh , " EDAC device not ready " ) ;
shell_error ( sh , " IBECC device not ready " ) ;
return - ENODEV ;
return - ENODEV ;
}
}
err = edac_inject_get_error_type ( dev , & error_type ) ;
err = edac_inject_get_error_type ( edac_ device , & error_type ) ;
if ( err ! = 0 ) {
if ( err ! = 0 ) {
shell_error ( sh , " Error getting error type (err %d) " , err ) ;
shell_error ( sh , " Error getting error type (err %d) " , err ) ;
return err ;
return err ;
@ -288,18 +271,15 @@ static int cmd_inject_error_type_show(const struct shell *sh, size_t argc,
static int set_error_type ( const struct shell * sh , uint32_t error_type )
static int set_error_type ( const struct shell * sh , uint32_t error_type )
{
{
const struct device * dev ;
if ( ! device_is_ready ( edac_device ) ) {
shell_error ( sh , " EDAC device not ready " ) ;
dev = DEVICE_DT_GET ( DT_NODELABEL ( ibecc ) ) ;
if ( ! device_is_ready ( dev ) ) {
shell_error ( sh , " IBECC device not ready " ) ;
return - ENODEV ;
return - ENODEV ;
}
}
shell_fprintf ( sh , SHELL_NORMAL , " Set injection error type: %s \n " ,
shell_fprintf ( sh , SHELL_NORMAL , " Set injection error type: %s \n " ,
get_error_type ( error_type ) ) ;
get_error_type ( error_type ) ) ;
return edac_inject_set_error_type ( dev , error_type ) ;
return edac_inject_set_error_type ( edac_ device , error_type ) ;
}
}
static int cmd_inject_error_type_cor ( const struct shell * sh , size_t argc ,
static int cmd_inject_error_type_cor ( const struct shell * sh , size_t argc ,
@ -314,24 +294,6 @@ static int cmd_inject_error_type_uc(const struct shell *sh, size_t argc,
return set_error_type ( sh , EDAC_ERROR_TYPE_DRAM_UC ) ;
return set_error_type ( sh , EDAC_ERROR_TYPE_DRAM_UC ) ;
}
}
static int cmd_inject_test ( const struct shell * sh , size_t argc , char * * argv )
{
const struct device * dev ;
dev = DEVICE_DT_GET ( DT_NODELABEL ( ibecc ) ) ;
if ( ! device_is_ready ( dev ) ) {
shell_error ( sh , " IBECC device not ready " ) ;
return - ENODEV ;
}
edac_inject_set_param1 ( dev , 0x1000 ) ;
edac_inject_set_param2 ( dev , INJ_ADDR_BASE_MASK_MASK ) ;
edac_inject_set_error_type ( dev , EDAC_ERROR_TYPE_DRAM_COR ) ;
edac_inject_error_trigger ( dev ) ;
return 0 ;
}
SHELL_STATIC_SUBCMD_SET_CREATE ( sub_inject_error_type_cmds ,
SHELL_STATIC_SUBCMD_SET_CREATE ( sub_inject_error_type_cmds ,
SHELL_CMD ( correctable , NULL , " Set correctable error type " ,
SHELL_CMD ( correctable , NULL , " Set correctable error type " ,
cmd_inject_error_type_cor ) ,
cmd_inject_error_type_cor ) ,
@ -341,18 +303,16 @@ SHELL_STATIC_SUBCMD_SET_CREATE(sub_inject_error_type_cmds,
) ;
) ;
/* EDAC Error Injection shell commands */
/* EDAC Error Injection shell commands */
SHELL_STATIC_SUBCMD_SET_CREATE ( sub_inject_cmds ,
SHELL_STATIC_SUBCMD_SET_CREATE (
SHELL_CMD ( addr , NULL , " Get / Set physical address " , cmd_inject_addr ) ,
sub_inject_cmds , SHELL_CMD ( param1 , NULL , " Get / Set injection param 1 " , cmd_inject_param1 ) ,
SHELL_CMD ( mask , NULL , " Get / Set address mask " , cmd_inject_mask ) ,
SHELL_CMD ( param2 , NULL , " Get / Set injection param 2 " , cmd_inject_param2 ) ,
SHELL_CMD_ARG ( trigger , NULL , " Trigger injection " , cmd_inject_trigger ,
SHELL_CMD_ARG ( trigger , NULL , " Trigger injection " , cmd_inject_trigger , 1 , 0 ) ,
1 , 0 ) ,
SHELL_CMD ( error_type , & sub_inject_error_type_cmds , " Get / Set injection error type " ,
SHELL_CMD ( error_type , & sub_inject_error_type_cmds ,
" Get / Set injection error type " ,
cmd_inject_error_type_show ) ,
cmd_inject_error_type_show ) ,
# ifdef CONFIG_X86
SHELL_CMD ( disable_nmi , NULL , " Disable NMI " , cmd_inject_disable_nmi ) ,
SHELL_CMD ( disable_nmi , NULL , " Disable NMI " , cmd_inject_disable_nmi ) ,
SHELL_CMD ( enable_nmi , NULL , " Enable NMI " , cmd_inject_enable_nmi ) ,
SHELL_CMD ( enable_nmi , NULL , " Enable NMI " , cmd_inject_enable_nmi ) ,
SHELL_CMD_ARG ( test_default , NULL , " Test default injection parameters " ,
# endif /* CONFIG_X86 */
cmd_inject_test , 1 , 0 ) ,
SHELL_SUBCMD_SET_END /* Array terminated */
SHELL_SUBCMD_SET_END /* Array terminated */
) ;
) ;
# endif /* CONFIG_EDAC_ERROR_INJECT */
# endif /* CONFIG_EDAC_ERROR_INJECT */
@ -360,30 +320,25 @@ SHELL_STATIC_SUBCMD_SET_CREATE(sub_inject_cmds,
static int cmd_ecc_error_show ( const struct shell * sh , size_t argc ,
static int cmd_ecc_error_show ( const struct shell * sh , size_t argc ,
char * * argv )
char * * argv )
{
{
const struct device * dev ;
if ( ! device_is_ready ( edac_device ) ) {
shell_error ( sh , " EDAC device not ready " ) ;
dev = DEVICE_DT_GET ( DT_NODELABEL ( ibecc ) ) ;
if ( ! device_is_ready ( dev ) ) {
shell_error ( sh , " IBECC device not ready " ) ;
return - ENODEV ;
return - ENODEV ;
}
}
return ecc_error_show ( sh , dev ) ;
return ecc_error_show ( sh , edac_ device ) ;
}
}
static int cmd_ecc_error_clear ( const struct shell * sh , size_t argc ,
static int cmd_ecc_error_clear ( const struct shell * sh , size_t argc ,
char * * argv )
char * * argv )
{
{
const struct device * dev ;
int err ;
int err ;
dev = DEVICE_DT_GET ( DT_NODELABEL ( ibecc ) ) ;
if ( ! device_is_ready ( edac_device ) ) {
if ( ! device_is_ready ( dev ) ) {
shell_error ( sh , " EDAC device not ready " ) ;
shell_error ( sh , " IBECC device not ready " ) ;
return - ENODEV ;
return - ENODEV ;
}
}
err = edac_ecc_error_log_clear ( dev ) ;
err = edac_ecc_error_log_clear ( edac_ device ) ;
if ( err ! = 0 ) {
if ( err ! = 0 ) {
shell_error ( sh , " Error clear ecc error log (err %d) " ,
shell_error ( sh , " Error clear ecc error log (err %d) " ,
err ) ;
err ) ;
@ -404,30 +359,25 @@ SHELL_STATIC_SUBCMD_SET_CREATE(sub_ecc_error_cmds,
static int cmd_parity_error_show ( const struct shell * sh , size_t argc ,
static int cmd_parity_error_show ( const struct shell * sh , size_t argc ,
char * * argv )
char * * argv )
{
{
const struct device * dev ;
if ( ! device_is_ready ( edac_device ) ) {
shell_error ( sh , " EDAC device not ready " ) ;
dev = DEVICE_DT_GET ( DT_NODELABEL ( ibecc ) ) ;
if ( ! device_is_ready ( dev ) ) {
shell_error ( sh , " IBECC device not ready " ) ;
return - ENODEV ;
return - ENODEV ;
}
}
return parity_error_show ( sh , dev ) ;
return parity_error_show ( sh , edac_ device ) ;
}
}
static int cmd_parity_error_clear ( const struct shell * sh , size_t argc ,
static int cmd_parity_error_clear ( const struct shell * sh , size_t argc ,
char * * argv )
char * * argv )
{
{
const struct device * dev ;
int err ;
int err ;
dev = DEVICE_DT_GET ( DT_NODELABEL ( ibecc ) ) ;
if ( ! device_is_ready ( edac_device ) ) {
if ( ! device_is_ready ( dev ) ) {
shell_error ( sh , " EDAC device not ready " ) ;
shell_error ( sh , " IBECC device not ready " ) ;
return - ENODEV ;
return - ENODEV ;
}
}
err = edac_parity_error_log_clear ( dev ) ;
err = edac_parity_error_log_clear ( edac_ device ) ;
if ( err ! = 0 ) {
if ( err ! = 0 ) {
shell_error ( sh , " Error clear parity error log (err %d) " ,
shell_error ( sh , " Error clear parity error log (err %d) " ,
err ) ;
err ) ;