diff options
| author | Dan Crowell <dcrowell@us.ibm.com> | 2014-01-24 15:47:52 -0600 |
|---|---|---|
| committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2014-02-14 12:32:47 -0600 |
| commit | 5850220077f29041920e83de66ec458dac9c82a7 (patch) | |
| tree | 5b89744aa9e0f7c07ba9f2c341a66d4954b04f8d /src/usr/scom | |
| parent | 54fe1fd5efa72aa626419e56e89d68e83480a0db (diff) | |
| download | talos-hostboot-5850220077f29041920e83de66ec458dac9c82a7.tar.gz talos-hostboot-5850220077f29041920e83de66ec458dac9c82a7.zip | |
Finalize callouts for scan and scom drivers
Change-Id: Iaa603e8464d4e342fa256560da3c9d529aae8be4
RTC: 47014
Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/8340
Reviewed-by: Douglas R. Gilbert <dgilbert@us.ibm.com>
Tested-by: Jenkins Server
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/usr/scom')
| -rw-r--r-- | src/usr/scom/scom.C | 362 | ||||
| -rw-r--r-- | src/usr/scom/scom.H | 71 | ||||
| -rw-r--r-- | src/usr/scom/scomtrans.C | 49 |
3 files changed, 256 insertions, 226 deletions
diff --git a/src/usr/scom/scom.C b/src/usr/scom/scom.C index 8030d52b5..ae83f7769 100644 --- a/src/usr/scom/scom.C +++ b/src/usr/scom/scom.C @@ -38,6 +38,8 @@ #include <scom/scomreasoncodes.H> #include <ibscom/ibscomreasoncodes.H> #include <sys/time.h> +#include <xscom/piberror.H> +#include <errl/errludtarget.H> // Trace definition @@ -101,28 +103,29 @@ errlHndl_t checkIndirectAndDoScom(DeviceFW::OperationType i_opType, enum { MAX_INDSCOM_TIMEOUT_NS = 100000 }; //=.1ms - // In HOSTBOOT_RUNTIME we always defer indirect scoms to Sapphire. + mutex_t* l_mutex = NULL; + bool need_unlock = false; + + do { + // In HOSTBOOT_RUNTIME we always defer indirect scoms to Sapphire. #ifndef __HOSTBOOT_RUNTIME - // If the indirect scom bit is 0, then doing a regular scom - if( (i_addr & 0x8000000000000000) == 0) - { + // If the indirect scom bit is 0, then doing a regular scom + if( (i_addr & 0x8000000000000000) == 0) + { #endif // __HOSTBOOT_RUNTIME - l_err = doScomOp(i_opType, - i_target, - io_buffer, - io_buflen, - i_accessType, - i_addr); + l_err = doScomOp(i_opType, + i_target, + io_buffer, + io_buflen, + i_accessType, + i_addr); + //all done + break; #ifndef __HOSTBOOT_RUNTIME - } - // We are performing an indirect scom. - else - { - mutex_t* l_mutex = NULL; - uint64_t elapsed_indScom_time_ns = 0; - bool l_indScomError = false; - uint64_t temp_io_buffer = 0; + } + // We are performing an indirect scom. + uint64_t elapsed_indScom_time_ns = 0; uint64_t l_io_buffer = 0; uint64_t temp_scomAddr = 0; @@ -155,6 +158,7 @@ errlHndl_t checkIndirectAndDoScom(DeviceFW::OperationType i_opType, i_target->getHbMutexAttr<TARGETING::ATTR_SCOM_IND_MUTEX>(); mutex_lock(l_mutex); + need_unlock = true; // turn the read bit on. l_io_buffer = l_io_buffer | 0x8000000000000000; @@ -170,20 +174,20 @@ errlHndl_t checkIndirectAndDoScom(DeviceFW::OperationType i_opType, if (l_err != NULL) { - mutex_unlock(l_mutex); - return l_err; + break; } - // Need to check loop on read until either - // bit (32) = 1 or we have exceeded our max - // retries. + // Need to check loop on read until we see done, error, + // or we timeout + IndirectScom_t scomout; + scomout.data64 = 0; do { // Now perform the op requested using the passed in // IO_Buffer to pass the read data back to caller. l_err = doScomOp(i_opType, i_target, - io_buffer, + &(scomout.data64), io_buflen, i_accessType, i_addr); @@ -194,27 +198,9 @@ errlHndl_t checkIndirectAndDoScom(DeviceFW::OperationType i_opType, } // if bit 32 is on indicating a complete bit - if ((*((uint64_t *)io_buffer) & SCOM_IND_COMPLETE_MASK) - == SCOM_IND_COMPLETE_MASK) + // or we saw an error, then we're done + if (scomout.done || scomout.piberr) { - // check for bits 33-35 to be 0 - // indicating the read is valid - if ((*((uint64_t *)io_buffer) & SCOM_IND_ERROR_MASK) - == 0) - - { - // Clear out the other bits in the io_buffer - // register to only return the read data to caller - *((uint64_t *)io_buffer) &= 0x00000000000FFFF; - - } - else - { - // indicate that we do have a indirect scom failure - l_indScomError = true; - } - - // break out because we got the complete bit.. break; } @@ -224,64 +210,80 @@ errlHndl_t checkIndirectAndDoScom(DeviceFW::OperationType i_opType, }while ( elapsed_indScom_time_ns <= MAX_INDSCOM_TIMEOUT_NS); mutex_unlock(l_mutex); + need_unlock = false; - if (l_err == NULL) - { - if (l_indScomError == true) - { - // got an indirect read error - // the data buffer is in tempIoData - TRACFCOMP(g_trac_scom, - "INDIRECT SCOM READ= ERROR valid bits are not on.. scomreg=0x%.16X", - *((uint64_t *)io_buffer)); - - /*@ - * @errortype - * @moduleid SCOM::SCOM_CHECK_INDIRECT_AND_DO_SCOM - * @reasoncode SCOM::SCOM_INDIRECT_READ_FAIL - * @userdata1 Address - * @userdata2 Scom data read from Address - * @devdesc Indirect SCOM Read error - */ - l_err = new ERRORLOG::ErrlEntry( - ERRORLOG::ERRL_SEV_UNRECOVERABLE, - SCOM_CHECK_INDIRECT_AND_DO_SCOM, - SCOM_INDIRECT_READ_FAIL, - i_addr, - *((uint64_t *)io_buffer)); - - //@TODO - add usr details to the errorlog when we have one to - // give better info regarding the fail.. - - } - // if we got a timeout, create an errorlog. - else if( elapsed_indScom_time_ns > MAX_INDSCOM_TIMEOUT_NS ) - { - // got an indirect read timeout - TRACFCOMP(g_trac_scom, - "INDIRECT SCOM READ=indirect read timout .. scomreg=0x%.16X", - *((uint64_t *)io_buffer)); - - - /*@ - * @errortype - * @moduleid SCOM::SCOM_CHECK_INDIRECT_AND_DO_SCOM - * @reasoncode SCOM::SCOM_INDIRECT_READ_TIMEOUT - * @userdata1 Address - * @userdata2 Scom data read from Address - * @devdesc Indirect SCOM complete bit did not come on - */ - l_err = new ERRORLOG::ErrlEntry( - ERRORLOG::ERRL_SEV_UNRECOVERABLE, - SCOM_CHECK_INDIRECT_AND_DO_SCOM, - SCOM_INDIRECT_READ_TIMEOUT, - i_addr, - *((uint64_t *)io_buffer)); - - //@TODO - add usr details to the errorlog when we have - // one to give better info regarding the fail.. + if (l_err) { break; } - } + // Check for a PCB/PIB Error + if( scomout.piberr != 0 ) + { + // got an indirect read error + // the data buffer is in tempIoData + TRACFCOMP(g_trac_scom, + "INDIRECT SCOM READ: PIB Error=%d (reg=0x%.16X)", + scomout.piberr, scomout.data64); + + /*@ + * @errortype + * @moduleid SCOM::SCOM_CHECK_INDIRECT_AND_DO_SCOM + * @reasoncode SCOM::SCOM_INDIRECT_READ_FAIL + * @userdata1 Address + * @userdata2 Indirect Scom Status Register + * @devdesc Indirect SCOM Read error + */ + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SCOM_CHECK_INDIRECT_AND_DO_SCOM, + SCOM_INDIRECT_READ_FAIL, + i_addr, + scomout.data64); + + //Add the callouts for the specific PCB/PIB error + PIB::addFruCallouts( i_target, + scomout.piberr, + l_err ); + + //Add this target to the FFDC + ERRORLOG::ErrlUserDetailsTarget(i_target,"IndSCOM Target") + .addToLog(l_err); + } + // if we got a timeout, create an errorlog. + else if( scomout.done == 0 ) + { + // got an indirect read timeout + TRACFCOMP(g_trac_scom, + "INDIRECT SCOM READ: Timeout, reg=0x%.16X", + scomout.data64); + + /*@ + * @errortype + * @moduleid SCOM::SCOM_CHECK_INDIRECT_AND_DO_SCOM + * @reasoncode SCOM::SCOM_INDIRECT_READ_TIMEOUT + * @userdata1 Address + * @userdata2 Indirect Scom Status Register + * @devdesc Indirect SCOM complete bit did not come on + */ + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SCOM_CHECK_INDIRECT_AND_DO_SCOM, + SCOM_INDIRECT_READ_TIMEOUT, + i_addr, + scomout.data64); + + //Best guess is the chip + l_err->addHwCallout( i_target, + HWAS::SRCI_PRIORITY_HIGH, + HWAS::DECONFIG, + HWAS::GARD_Predictive ); + + //Add this target to the FFDC + ERRORLOG::ErrlUserDetailsTarget(i_target,"IndSCOM Target") + .addToLog(l_err); + } + else // It worked + { + uint64_t tmp = static_cast<uint64_t>(scomout.data); + memcpy( io_buffer, &tmp, sizeof(uint64_t) ); } } else //write @@ -290,7 +292,7 @@ errlHndl_t checkIndirectAndDoScom(DeviceFW::OperationType i_opType, l_io_buffer = l_io_buffer & 0x7FFFFFFFFFFFFFFF; // Now perform the op requested using the - // locai io_buffer with the indirect addr imbedded. + // local io_buffer with the indirect addr imbedded. l_err = doScomOp(i_opType, i_target, & l_io_buffer, @@ -298,46 +300,30 @@ errlHndl_t checkIndirectAndDoScom(DeviceFW::OperationType i_opType, i_accessType, i_addr); - // Need to check loop on read until either - // bit (32) = 1 or we have exceeded our max - // retries. + // Need to check loop on read until we see done, error, + // or we timeout + IndirectScom_t scomout; + scomout.data64 = 0; do { - - memcpy(&temp_io_buffer, io_buffer, 8); - - // Now perform the op requested using the passed in - // IO_Buffer to pass the read data back to caller. + // Now look for status l_err = doScomOp(DeviceFW::READ, i_target, - & temp_io_buffer, + &(scomout.data64), io_buflen, i_accessType, i_addr); - if (l_err != NULL) { break; } // if bit 32 is on indicating a complete bit - if ((temp_io_buffer & SCOM_IND_COMPLETE_MASK) - == SCOM_IND_COMPLETE_MASK) + // or we saw an error, then we're done + if (scomout.done || scomout.piberr) { - // The write is valid when bits 33-35 are 0.. - // if not on return error - if ((temp_io_buffer & SCOM_IND_ERROR_MASK) - != 0) - - { - // bits did not get turned on.. set error to true. - l_indScomError = true; - } - - // break out because we got the complete bit on break; - } nanosleep( 0, 10000 ); //sleep for 10,000 ns @@ -345,66 +331,80 @@ errlHndl_t checkIndirectAndDoScom(DeviceFW::OperationType i_opType, }while ( elapsed_indScom_time_ns <= MAX_INDSCOM_TIMEOUT_NS); - if (l_err == NULL) - { - // If the indirect scom has an error. - if (l_indScomError == true) - { - // got an indirect write error - TRACFCOMP(g_trac_scom, "INDIRECT SCOM WRITE= ERROR valid bits are not on.. scomreg=0x%.16X", temp_io_buffer); - - /*@ - * @errortype - * @moduleid SCOM::SCOM_CHECK_INDIRECT_AND_DO_SCOM - * @reasoncode SCOM::SCOM_INDIRECT_WRITE_FAIL - * @userdata1 Address - * @userdata2 Scom data read from Address - * @devdesc Indirect SCOM Write failed for this address - */ - l_err = new ERRORLOG::ErrlEntry( - ERRORLOG::ERRL_SEV_UNRECOVERABLE, - SCOM_CHECK_INDIRECT_AND_DO_SCOM, - SCOM_INDIRECT_WRITE_FAIL, - i_addr, - temp_io_buffer); - - //@TODO - add usr details to the errorlog when we have - // one to give better info regarding the fail.. + if (l_err) { break; } - } - // if we got a timeout, create an errorlog. - else if( elapsed_indScom_time_ns > MAX_INDSCOM_TIMEOUT_NS ) - { - // got an indirect write timeout - TRACFCOMP(g_trac_scom, - "INDIRECT SCOM WRITE=indirect write timeout .. scomreg=0x%.16X", - temp_io_buffer); - - - /*@ - * @errortype - * @moduleid SCOM::SCOM_CHECK_INDIRECT_AND_DO_SCOM - * @reasoncode SCOM::SCOM_INDIRECT_WRITE_TIMEOUT - * @userdata1 Address - * @userdata2 Scom data read from Address - * @devdesc Indirect SCOM write timeout, complete - * bit did not come one - */ - l_err = new ERRORLOG::ErrlEntry( - ERRORLOG::ERRL_SEV_UNRECOVERABLE, - SCOM_CHECK_INDIRECT_AND_DO_SCOM, - SCOM_INDIRECT_WRITE_TIMEOUT, - i_addr, - temp_io_buffer); - - //@TODO - add usr details to the errorlog when we have - // one to give better info regarding the fail.. - - } + // Check for a PCB/PIB Error + if( scomout.piberr != 0 ) + { + // got an indirect write error + TRACFCOMP(g_trac_scom, "INDIRECT SCOM PIB Error=%d (reg=0x%.16X)", scomout.piberr, scomout.data64); + + /*@ + * @errortype + * @moduleid SCOM::SCOM_CHECK_INDIRECT_AND_DO_SCOM + * @reasoncode SCOM::SCOM_INDIRECT_WRITE_FAIL + * @userdata1 Address + * @userdata2 Indirect Scom Status Register + * @devdesc Indirect SCOM Write failed for this address + */ + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SCOM_CHECK_INDIRECT_AND_DO_SCOM, + SCOM_INDIRECT_WRITE_FAIL, + i_addr, + scomout.data64); + + //Add the callouts for the specific PCB/PIB error + PIB::addFruCallouts( i_target, + scomout.piberr, + l_err ); + + //Add this target to the FFDC + ERRORLOG::ErrlUserDetailsTarget(i_target,"IndSCOM Target") + .addToLog(l_err); + } + // if we got a timeout, create an errorlog. + else if( scomout.done == 0 ) + { + // got an indirect read timeout + TRACFCOMP(g_trac_scom, + "INDIRECT SCOM WRITE: Timeout, reg=0x%.16X", + scomout.data64); + + /*@ + * @errortype + * @moduleid SCOM::SCOM_CHECK_INDIRECT_AND_DO_SCOM + * @reasoncode SCOM::SCOM_INDIRECT_WRITE_TIMEOUT + * @userdata1 Address + * @userdata2 Indirect Scom Status Register + * @devdesc Indirect SCOM complete bit did not come on + */ + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SCOM_CHECK_INDIRECT_AND_DO_SCOM, + SCOM_INDIRECT_WRITE_TIMEOUT, + i_addr, + scomout.data64); + + //Best guess is the chip + l_err->addHwCallout( i_target, + HWAS::SRCI_PRIORITY_HIGH, + HWAS::DECONFIG, + HWAS::GARD_Predictive ); + + //Add this target to the FFDC + ERRORLOG::ErrlUserDetailsTarget(i_target,"IndSCOM Target") + .addToLog(l_err); } } // end of write - } #endif // __HOSTBOOT_RUNTIME + } while(0); + + if( need_unlock ) + { + mutex_unlock(l_mutex); + } + return l_err; } diff --git a/src/usr/scom/scom.H b/src/usr/scom/scom.H index bcb9f2fe2..06416640b 100644 --- a/src/usr/scom/scom.H +++ b/src/usr/scom/scom.H @@ -1,25 +1,25 @@ -// IBM_PROLOG_BEGIN_TAG -// This is an automatically generated prolog. -// -// $Source: src/usr/scom/scom.H $ -// -// IBM CONFIDENTIAL -// -// COPYRIGHT International Business Machines Corp. 2011 -// -// p1 -// -// Object Code Only (OCO) source materials -// Licensed Internal Code Source Materials -// IBM HostBoot Licensed Internal Code -// -// The source code for this program is not published or other- -// wise divested of its trade secrets, irrespective of what has -// been deposited with the U.S. Copyright Office. -// -// Origin: 30 -// -// IBM_PROLOG_END +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/scom/scom.H $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2011,2014 */ +/* */ +/* p1 */ +/* */ +/* Object Code Only (OCO) source materials */ +/* Licensed Internal Code Source Materials */ +/* IBM HostBoot Licensed Internal Code */ +/* */ +/* The source code for this program is not published or otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ #ifndef __SCOM_H #define __SCOM_H @@ -31,13 +31,30 @@ namespace SCOM { - enum ScomErrorMask +/** + * @brief Indirect SCOM Status + */ +union IndirectScom_t +{ + uint64_t data64; + struct { - // checkf for complete bit .. bit 32 - SCOM_IND_COMPLETE_MASK = 0x0000000080000000, - //check for bits 33-35 - SCOM_IND_ERROR_MASK = 0x0000000070000000 + uint64_t :12; //0:11 + uint64_t addr:20; //12:31 + uint64_t done:1; //32 + uint64_t piberr:3; //33:35 + uint64_t userstat:4; //36:39 + uint64_t :8; //40:47 + uint64_t data:16; //48:63 }; +}; +enum ScomErrorMask +{ + // checkf for complete bit .. bit 32 + SCOM_IND_COMPLETE_MASK = 0x0000000080000000, + //check for bits 33-35 + SCOM_IND_ERROR_MASK = 0x0000000070000000 +}; diff --git a/src/usr/scom/scomtrans.C b/src/usr/scom/scomtrans.C index 024b2cd54..2f533ea5c 100644 --- a/src/usr/scom/scomtrans.C +++ b/src/usr/scom/scomtrans.C @@ -5,7 +5,7 @@ /* */ /* IBM CONFIDENTIAL */ /* */ -/* COPYRIGHT International Business Machines Corp. 2011,2013 */ +/* COPYRIGHT International Business Machines Corp. 2011,2014 */ /* */ /* p1 */ /* */ @@ -40,6 +40,7 @@ #include "scom.H" #include "scomtrans.H" #include <scom/scomreasoncodes.H> +#include <errl/errludtarget.H> // Trace definition extern trace_desc_t* g_trac_scom; @@ -512,9 +513,11 @@ errlHndl_t scomTranslate(DeviceFW::OperationType i_opType, SCOM_TRANSLATE, SCOM_TRANS_INVALID_TYPE, i_addr, - l_type); - - + l_type, + true/*SW Error*/); + //Add this target to the FFDC + ERRORLOG::ErrlUserDetailsTarget(i_target,"SCOM Target") + .addToLog(l_err); } } @@ -536,8 +539,12 @@ errlHndl_t scomTranslate(DeviceFW::OperationType i_opType, SCOM_TRANSLATE, SCOM_INVALID_ADDR, i_addr, - l_type); - l_err->collectTrace("SCOM",1024); + l_type, + true/*SW Error*/); + //Add this target to the FFDC + ERRORLOG::ErrlUserDetailsTarget(i_target,"SCOM Target") + .addToLog(l_err); + l_err->collectTrace(SCOM_COMP_NAME,1024); } @@ -587,6 +594,8 @@ errlHndl_t scomPerformTranslate(TARGETING::EntityPath i_epath, } else { + TRACFCOMP(g_trac_scom,"SCOMPERFORMTRANSLATE Invalid Address.i_addr =0x%X for mask = 0x%X", i_addr, i_mask); + /*@ * @errortype * @moduleid SCOM::SCOM_PERFORM_TRANSLATE @@ -596,14 +605,16 @@ errlHndl_t scomPerformTranslate(TARGETING::EntityPath i_epath, * @devdesc Invalid Address for the mask passed in. */ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, - SCOM_PERFORM_TRANSLATE, - SCOM_INVALID_ADDR, - i_addr, - o_target->getAttr<TARGETING::ATTR_TYPE>()); + SCOM_PERFORM_TRANSLATE, + SCOM_INVALID_ADDR, + i_addr, + o_target->getAttr<TARGETING::ATTR_TYPE>(), + true/*SW Error*/); + //Add this target to the FFDC + ERRORLOG::ErrlUserDetailsTarget(o_target,"SCOM Target") + .addToLog(l_err); - l_err->collectTrace("SCOM",1024); - - TRACFCOMP(g_trac_scom,"SCOMPERFORMTRANSLATE Invalid Address.i_addr =0x%X for mask = 0x%X", i_addr, i_mask); + l_err->collectTrace(SCOM_COMP_NAME,1024); return (l_err); } @@ -657,7 +668,7 @@ errlHndl_t scomfindParentTarget( TARGETING::EntityPath i_epath, if (!foundParent) { - // got and error.. bad address.. write an errorlog.. + TRACFCOMP(g_trac_scom, "TRANSLATE..Did not find parent type=0x%X ", i_ptype); /*@ * @errortype * @moduleid SCOM::SCOM_PERFORM_TRANSLATE @@ -670,12 +681,14 @@ errlHndl_t scomfindParentTarget( TARGETING::EntityPath i_epath, SCOM_FIND_PARENT_TARGET, SCOM_NO_MATCHING_PARENT, i_ptype, - o_target->getAttr<TARGETING::ATTR_TYPE>()); + o_target->getAttr<TARGETING::ATTR_TYPE>(), + true/*SW Error*/); - l_err->collectTrace("SCOM",1024); + //Add this target to the FFDC + ERRORLOG::ErrlUserDetailsTarget(o_target,"SCOM Target") + .addToLog(l_err); - // Need to write and errorlog and return.. - TRACFCOMP(g_trac_scom, "TRANSLATE..Did not find parent type=0x%X ", i_ptype); + l_err->collectTrace(SCOM_COMP_NAME,1024); } return l_err; |

