diff options
Diffstat (limited to 'src/usr/scom/scom.C')
-rw-r--r-- | src/usr/scom/scom.C | 362 |
1 files changed, 181 insertions, 181 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; } |