diff options
Diffstat (limited to 'src/usr/i2c/fapi_i2c_dd.C')
-rw-r--r-- | src/usr/i2c/fapi_i2c_dd.C | 74 |
1 files changed, 56 insertions, 18 deletions
diff --git a/src/usr/i2c/fapi_i2c_dd.C b/src/usr/i2c/fapi_i2c_dd.C index bf1771865..35a838998 100644 --- a/src/usr/i2c/fapi_i2c_dd.C +++ b/src/usr/i2c/fapi_i2c_dd.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2018 */ +/* Contributors Listed Below - COPYRIGHT 2018,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -41,6 +41,8 @@ #include <devicefw/driverif.H> #include <i2c/i2creasoncodes.H> #include "fapi_i2c_dd.H" +#include <time.h> +#include <stdio.h> extern trace_desc_t* g_trac_i2c; @@ -69,6 +71,11 @@ DEVICE_REGISTER_ROUTE( DeviceFW::WILDCARD, TARGETING::TYPE_OCMB_CHIP, fapiI2cPerformOp ); +DEVICE_REGISTER_ROUTE( DeviceFW::WILDCARD, + DeviceFW::FAPI_I2C, + TARGETING::TYPE_PMIC, + fapiI2cPerformOp ); + errlHndl_t fapiI2cPerformOp(DeviceFW::OperationType i_opType, TARGETING::Target * i_target, void * io_buffer, @@ -78,6 +85,7 @@ errlHndl_t fapiI2cPerformOp(DeviceFW::OperationType i_opType, { errlHndl_t l_err = nullptr; errlHndl_t l_err_retryable = nullptr; + bool l_non_retryable_err_hit = false; const uint8_t FAPI_I2C_MAX_RETRIES = 2; TARGETING::ATTR_FAPI_I2C_CONTROL_INFO_type l_i2cInfo; @@ -89,6 +97,10 @@ errlHndl_t fapiI2cPerformOp(DeviceFW::OperationType i_opType, l_cfgData = va_arg( i_args, uint8_t* ); } + timespec_t l_startTime; + timespec_t l_endTime; + clock_gettime(CLOCK_MONOTONIC, &l_startTime); + TRACUCOMP(g_trac_i2c, ENTER_MRK"fapiI2cPerformOp(): " "%s operation on target %.8X", (i_opType==DeviceFW::READ)?"READ":"WRITE", @@ -103,6 +115,18 @@ errlHndl_t fapiI2cPerformOp(DeviceFW::OperationType i_opType, break; } + // If the target has dynamic device address attribute, then use that instead of the + // read-only address found in ATTR_FAPI_I2C_CONTROL_INFO. We use the dynamic address + // attribute because ATTR_FAPI_I2C_CONTROL_INFO is not writable and its difficult + // to override complex attributes. + if(i_target->tryGetAttr<TARGETING::ATTR_DYNAMIC_I2C_DEVICE_ADDRESS>(l_i2cInfo.devAddr)) + { + TRACDCOMP(g_trac_i2c, + "Using DYNAMIC_I2C_DEVICE_ADDRESS %.2x for HUID %.8x", + l_i2cInfo.devAddr, + TARGETING::get_huid(i_target)); + } + // grab target pointer to master TARGETING::TargetService& ts = TARGETING::targetService(); TARGETING::Target * i2cm = ts.toTarget(l_i2cInfo.i2cMasterPath); @@ -136,8 +160,6 @@ errlHndl_t fapiI2cPerformOp(DeviceFW::OperationType i_opType, TARGETING::get_huid(i_target), 0, true /*Add HB SW Callout*/ ); - - l_err->collectTrace( I2C_COMP_NAME ); break; } @@ -164,8 +186,6 @@ errlHndl_t fapiI2cPerformOp(DeviceFW::OperationType i_opType, i_opType, TARGETING::get_huid(i_target), true /*Add HB SW Callout*/ ); - - l_err->collectTrace( I2C_COMP_NAME ); break; } @@ -204,8 +224,7 @@ errlHndl_t fapiI2cPerformOp(DeviceFW::OperationType i_opType, "Error: rc=0x%X, tgt=0x%X, No Retry (retry=%d)", l_err->reasonCode(), TARGETING::get_huid(i_target), retry); - l_err->collectTrace(I2C_COMP_NAME); - + l_non_retryable_err_hit = true; // break from retry loop break; } @@ -267,35 +286,54 @@ errlHndl_t fapiI2cPerformOp(DeviceFW::OperationType i_opType, } // end of retryable error loop + clock_gettime(CLOCK_MONOTONIC, &l_endTime); + char l_time_str[128]; + snprintf(l_time_str, sizeof(l_time_str), + "Start Time: %lu sec %lu ns End Time: %lu sec %lu ns", + l_startTime.tv_sec, l_startTime.tv_nsec, + l_endTime.tv_sec, l_endTime.tv_nsec); + // Handle saved retryable error, if any if (l_err_retryable) { - if (l_err) + // This is the case where we had 1 or more retryable errors and + // eventually hit a non retryable error. + if (l_err && l_non_retryable_err_hit) { // commit original retryable error with new err PLID l_err_retryable->plid(l_err->plid()); TRACFCOMP(g_trac_i2c, "fapiI2cPerformOp(): Committing saved " "retryable error eid=0x%X with plid of returned err 0x%X", l_err_retryable->eid(), l_err_retryable->plid()); - + ERRORLOG::ErrlUserDetailsString(l_time_str) + .addToLog(l_err_retryable); ERRORLOG::ErrlUserDetailsTarget(i_target) .addToLog(l_err_retryable); l_err_retryable->collectTrace(I2C_COMP_NAME); + l_err_retryable->setSev(ERRORLOG::ERRL_SEV_INFORMATIONAL); errlCommit(l_err_retryable, I2C_COMP_ID); } else { - // Since we eventually succeeded, - // delete original retryable error - TRACUCOMP(g_trac_i2c, "fapiI2cPerformOp(): Op successful, " - "deleting saved retryable err eid=0x%X, plid=0x%X", + // In this case we have either hit the max retryable errors and + // failed, or hit one or more retryable errors and eventually + // passed. Either way we do not need this l_err_retryable anymore. + TRACUCOMP(g_trac_i2c, "fapiI2cPerformOp(): Op successful, or we hit max Retries and" + " the caller is polling on this i2c op. Deleting saved retryable err eid=0x%X," + " plid=0x%X.", l_err_retryable->eid(), l_err_retryable->plid()); - delete l_err_retryable; l_err_retryable = nullptr; } } + if(l_err) + { + ERRORLOG::ErrlUserDetailsString(l_time_str) + .addToLog(l_err); + l_err->collectTrace(I2C_COMP_NAME); + } + } while (0); return l_err; @@ -376,10 +414,10 @@ errlHndl_t i2cWrite( TARGETING::Target * i_target, i_buffer, io_buffer_size, DEVICE_I2C_ADDRESS(i_i2cInfo->port, - i_i2cInfo->engine, - i_i2cInfo->devAddr, - i_i2cInfo->i2cMuxBusSelector, - &(i_i2cInfo->i2cMuxPath) ) ); + i_i2cInfo->engine, + i_i2cInfo->devAddr, + i_i2cInfo->i2cMuxBusSelector, + &(i_i2cInfo->i2cMuxPath) ) ); if( l_err ) { |