diff options
Diffstat (limited to 'src/usr/fapi2')
-rw-r--r-- | src/usr/fapi2/attribute_service.C | 441 | ||||
-rw-r--r-- | src/usr/fapi2/dimmBadDqBitmapFuncs.C | 25 | ||||
-rwxr-xr-x | src/usr/fapi2/fapi2.mk | 12 | ||||
-rwxr-xr-x | src/usr/fapi2/platCreateHwpErrParser.pl | 11 | ||||
-rw-r--r-- | src/usr/fapi2/plat_mmio_access.C | 310 | ||||
-rw-r--r-- | src/usr/fapi2/plat_spd_access.C | 122 | ||||
-rw-r--r-- | src/usr/fapi2/plat_utils.C | 22 | ||||
-rw-r--r-- | src/usr/fapi2/rowRepairsFuncs.C | 12 | ||||
-rw-r--r-- | src/usr/fapi2/test/fapi2DdimmGetEfdTest.C | 3 | ||||
-rw-r--r-- | src/usr/fapi2/test/fapi2GetChildrenTest.H | 135 | ||||
-rw-r--r-- | src/usr/fapi2/test/fapi2GetVpdTest.H | 6 | ||||
-rw-r--r-- | src/usr/fapi2/test/fapi2MmioAccessTest.H | 70 | ||||
-rw-r--r-- | src/usr/fapi2/test/fapi2MvpdTestCxx.H | 6 | ||||
-rw-r--r-- | src/usr/fapi2/test/fapi2SpdTestCxx.H | 194 | ||||
-rw-r--r-- | src/usr/fapi2/test/fapi2Test.mk | 2 | ||||
-rw-r--r-- | src/usr/fapi2/test/fapi2TestUtils.H | 3 | ||||
-rw-r--r-- | src/usr/fapi2/test/p9_mmiotests.C | 31 |
17 files changed, 1144 insertions, 261 deletions
diff --git a/src/usr/fapi2/attribute_service.C b/src/usr/fapi2/attribute_service.C index 0c7442fd9..4b994fe65 100644 --- a/src/usr/fapi2/attribute_service.C +++ b/src/usr/fapi2/attribute_service.C @@ -48,12 +48,14 @@ #include <target.H> #include <target_types.H> #include <hwpf_fapi2_reasoncodes.H> +#include <chipids.H> #include <devicefw/driverif.H> #include <plat_attr_override_sync.H> #include <vpd/spdenums.H> #include <p9_pm_get_poundv_bucket_attr.H> #include <p9_pm_get_poundw_bucket_attr.H> +#include <p9_frequency_buckets.H> #include <errl/errlmanager.H> #include <targeting/common/targetservice.H> @@ -178,11 +180,11 @@ errlHndl_t getTargetingTarget(const Target<TARGET_TYPE_ALL>& i_pFapiTarget, return l_errl; } -bool getTargetingAttrHelper(TARGETING::Target * l_pTargTarget, +bool getTargetingAttrHelper(TARGETING::Target * i_pTargTarget, const TARGETING::ATTRIBUTE_ID i_targAttrId, const uint32_t i_attrSize, void * o_pAttr) { - return l_pTargTarget->_tryGetAttr(i_targAttrId, i_attrSize, o_pAttr); + return i_pTargTarget->_tryGetAttr(i_targAttrId, i_attrSize, o_pAttr); } /// @@ -365,9 +367,52 @@ ReturnCode platGetTargetName(const Target<TARGET_TYPE_ALL>& i_pFapiTarget, { o_name = ENUM_ATTR_NAME_AXONE; } - else if (l_model == TARGETING::MODEL_EXPLORER) + else if (l_model == TARGETING::MODEL_OCMB) { - o_name = ENUM_ATTR_NAME_EXPLORER; + // For MODEL_OCMB the ATTR_CHIP_ID determines if it is a + // Gemini or an Explorer chip + uint32_t l_chipID = + l_pHbTarget->getAttr<TARGETING::ATTR_CHIP_ID>(); + + if (l_chipID == POWER_CHIPID::EXPLORER_16) + { + o_name = ENUM_ATTR_NAME_EXPLORER; + } + else if (l_chipID == POWER_CHIPID::GEMINI_16) + { + o_name = ENUM_ATTR_NAME_GEMINI; + } + else + { + FAPI_ERR("platGetTargetName. Unknown CHIP_ID 0x%x for MODEL_OCMB 0x%x", l_chipID, l_model); + + /*@ + * @errortype + * @moduleid fapi2::MOD_FAPI2_GET_TARGETING_TARGET + * @reasoncode RC_UNKNOWN_OCMB_CHIP_TYPE + * @userdata1[0:31] FAPI2 Type + * @userdata1[32:63] HB Target HUID + * @userdata2[0:31] HB Type + * @userdata2[32:63] HB Target CHIP_ID + * @devdesc HB OCMB_CHIP target found with unknown + * model based on ATTR_CHIP_ID + * @custdesc Firmware Error + */ + l_errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + MOD_FAPI2_GET_TARGETING_TARGET, + RC_UNKNOWN_OCMB_CHIP_TYPE, + TWO_UINT32_TO_UINT64( + i_pFapiTarget.getType(), + TARGETING::get_huid(l_pHbTarget) + ), + TWO_UINT32_TO_UINT64( + l_pHbTarget-> + getAttr<TARGETING::ATTR_TYPE>(), + l_chipID)); + + l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_errl)); + break; + } } else { @@ -466,6 +511,40 @@ ReturnCode platGetTargetPos(const Target<TARGET_TYPE_ALL>& i_pFapiTarget, } //****************************************************************************** +// fapi::platAttrSvc::platErrorOnSet function +//****************************************************************************** +ReturnCode platErrorOnSet( TARGETING::Target * i_pTargTarget, + const fapi2::AttributeId i_fapiAttrId ) +{ + // Just create an error to return back + FAPI_ERR("platErrorOnSet: Set not valid for Attribute %X on Target %.8X", + i_fapiAttrId, TARGETING::get_huid(i_pTargTarget) ); + /*@ + * @errortype + * @moduleid fapi2::MOD_FAPI2_PLAT_ERROR_ON_SET + * @reasoncode fapi2::RC_SET_ATTR_NOT_VALID + * @userdata1 Target HUID + * @userdata2 FAPI Attribute Id + * @devdesc platErrorOnSet> Set operation not valid + * @custdesc Firmware error + */ + errlHndl_t l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + fapi2::MOD_FAPI2_PLAT_ERROR_ON_SET, + fapi2::RC_SET_ATTR_NOT_VALID, + TARGETING::get_huid(i_pTargTarget), + i_fapiAttrId, + ERRORLOG::ErrlEntry::ADD_SW_CALLOUT); + l_errl->collectTrace(FAPI_TRACE_NAME); + l_errl->collectTrace(FAPI_IMP_TRACE_NAME); + + // attach our log to the fapi RC and return it + ReturnCode l_rc; + l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_errl)); + return l_rc; +} + +//****************************************************************************** // fapi::platAttrSvc::platGetFusedCoreMode function //****************************************************************************** ReturnCode platGetFusedCoreMode(uint8_t & o_isFused) @@ -2001,6 +2080,7 @@ ReturnCode platGetDQAttrISDIMM( } else { + mutex_lock(&l_C4DQmutex); auto l_huid = TARGETING::get_huid(l_pTarget); auto l_iterator = std::find ( l_cachedC4DQValues.begin(), l_cachedC4DQValues.end(), @@ -2013,14 +2093,13 @@ ReturnCode platGetDQAttrISDIMM( l_kvPair.huid = l_huid; rc = getDQAttrISDIMM(l_fapiTarget, l_kvPair.value); memcpy(o_vpdIsDimmTOC4DQVal, l_kvPair.value, sizeof(ATTR_CEN_VPD_ISDIMMTOC4DQ_Type)); - mutex_lock(&l_C4DQmutex); l_cachedC4DQValues.push_back(l_kvPair); - mutex_unlock(&l_C4DQmutex); } else { memcpy(o_vpdIsDimmTOC4DQVal, (*l_iterator).value, sizeof(ATTR_CEN_VPD_ISDIMMTOC4DQ_Type)); } + mutex_unlock(&l_C4DQmutex); } return rc; @@ -2052,6 +2131,7 @@ ReturnCode platGetDQSAttrISDIMM( } else { + mutex_lock(&l_C4DQSmutex); auto l_huid = TARGETING::get_huid(l_pTarget); auto l_iterator = std::find ( l_cachedC4DQSValues.begin(), l_cachedC4DQSValues.end(), @@ -2065,14 +2145,13 @@ ReturnCode platGetDQSAttrISDIMM( l_kvPair.huid = l_huid; rc = getDQSAttrISDIMM(l_fapiTarget, l_kvPair.value); memcpy(o_vpdIsDimmTOC4DQSVal, l_kvPair.value, sizeof(ATTR_CEN_VPD_ISDIMMTOC4DQS_Type)); - mutex_lock(&l_C4DQSmutex); l_cachedC4DQSValues.push_back(l_kvPair); - mutex_unlock(&l_C4DQSmutex); } else { memcpy(o_vpdIsDimmTOC4DQSVal, (*l_iterator).value, sizeof(ATTR_CEN_VPD_ISDIMMTOC4DQS_Type)); } + mutex_unlock(&l_C4DQSmutex); } return rc; @@ -2652,11 +2731,12 @@ ReturnCode platGetMBvpdSlopeInterceptData( return rc; } +#ifndef CONFIG_AXONE //****************************************************************************** // fapi::platAttrSvc::platGetFreqMcaMhz function //****************************************************************************** ReturnCode platGetFreqMcaMhz(const Target<TARGET_TYPE_ALL>& i_fapiTarget, - uint32_t & o_val) + ATTR_FREQ_MCA_MHZ_Type & o_val) { // The POR config for Cumulus is to run the MC/DMI clocks directly // off of the NEST PLL in 'sync' mode. To support 'sync' mode FW @@ -2679,7 +2759,350 @@ ReturnCode platGetFreqMcaMhz(const Target<TARGET_TYPE_ALL>& i_fapiTarget, return l_rc; } +#else + +/// @brief This function is called by the FAPI_ATTR_GET functions that lookup +/// values in the MEM_PLL_FREQ_BUCKETS tree. The key's used to lookup values in that +/// tree are the ATTR_FREQ_OMI_MHZ and ATTR_OMI_PLL_VCO attributes. These are on the +/// processor target but it is expected that all of the values match. +/// @param[out] o_omiFreq OMI Frequency of the system +/// @param[out] o_omiVco OMI VCO of the system +/// @return ReturnCode Zero on success, else platform specified error. +errlHndl_t getOmiFreqAndVco(TARGETING::ATTR_FREQ_OMI_MHZ_type & o_omiFreq, + TARGETING::ATTR_OMI_PLL_VCO_type & o_omiVco) +{ + errlHndl_t l_errl = nullptr; + + // Get all functional Proc targets + TARGETING::TargetHandleList l_procsList; + getAllChips(l_procsList, TARGETING::TYPE_PROC); + uint8_t l_firstValidProc = 0; + bool l_outValueSet = false; + + // Until we are told we need to support individual processor frequency + // assert that all of the processors have the same values + for(uint8_t i = 0; i < l_procsList.size(); i++) + { + // Get a list of functional OCMB targets under this processor + TARGETING::TargetHandleList l_childOcmbList; + TARGETING::getChildAffinityTargets(l_childOcmbList, l_procsList[i], + TARGETING::CLASS_CHIP, + TARGETING::TYPE_OCMB_CHIP); + // If there are no OCMB children for this processor then ignore it; + if(l_childOcmbList.size() == 0) + { + continue; + } + + // First valid processor's values will be used to compare against all other processors + if(!l_outValueSet) + { + o_omiFreq = l_procsList[i]->getAttr<TARGETING::ATTR_FREQ_OMI_MHZ>(); + o_omiVco = l_procsList[i]->getAttr<TARGETING::ATTR_OMI_PLL_VCO>(); + l_outValueSet = true; + l_firstValidProc = i; + continue; + } + + TARGETING::ATTR_FREQ_OMI_MHZ_type l_omiFreqToCmp = l_procsList[i]->getAttr<TARGETING::ATTR_FREQ_OMI_MHZ>(); + TARGETING::ATTR_OMI_PLL_VCO_type l_omiVcoToCmp = l_procsList[i]->getAttr<TARGETING::ATTR_OMI_PLL_VCO>(); + + // If this processors OMI freq is 0 then we have not determined this proc's OMI freq yet so we can ignore it. + // Otherwise, if we found that this processor's OMI freq / vco values do not match the first processor's values then + // return an error + if ((l_omiFreqToCmp != 0) && + (l_omiFreqToCmp != o_omiFreq || + l_omiVcoToCmp != o_omiVco )) + { + FAPI_ERR("platGetMcPllBucket: Detected two processors with difference OMI VCO / FREQ combinations." + " Proc 0x%.08X has OMI freq = %d and OMI vco = %d. " + " Proc 0x%.08X has OMI freq = %d and OMI vco = %d. " , + get_huid(l_procsList[l_firstValidProc]), o_omiFreq, o_omiVco, + get_huid(l_procsList[i]), l_omiFreqToCmp, l_omiVcoToCmp ); + /*@ + * @errortype + * @moduleid fapi2::MOD_GET_OMI_FREQ_AND_VCO + * @reasoncode fapi2::RC_PROC_FREQ_MISMATCH + * @userdata1[0:31] first ATTR_FREQ_OMI_MHZ found + * @userdata1[32:63] first ATTR_FREQ_PLL_VCO found + * @userdata2[0:31] ATTR_FREQ_OMI_MHZ mismatch found + * @userdata2[32:63] ATTR_FREQ_PLL_VCO mismatch found + * @devdesc Found mismatching processor attribute settings + * when we expect them to all be in sync + */ + l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + fapi2::MOD_GET_OMI_FREQ_AND_VCO, + fapi2::RC_NO_MATCHING_FREQ, + TWO_UINT32_TO_UINT64(o_omiFreq, o_omiVco), + TWO_UINT32_TO_UINT64(l_omiFreqToCmp, l_omiVcoToCmp), + ERRORLOG::ErrlEntry::NO_SW_CALLOUT); + l_errl->collectTrace(FAPI_IMP_TRACE_NAME, 256); + break; + } + } + + return l_errl; +} + +// OMI bucket descriptor +struct OmiFreqVcoBucketSelect_t +{ + uint32_t omifreq; // OMI Frequency in MHz + uint32_t vco; // VCO selector + uint8_t pll_bucket; // MCA Frequency in MHz +}; + + +//****************************************************************************** +// fapi::platAttrSvc::platGetMcPllBucket function +//****************************************************************************** +ReturnCode platGetMcPllBucket(const Target<TARGET_TYPE_ALL>& i_fapiTarget, + ATTR_MC_PLL_BUCKET_Type & o_val) +{ + fapi2::ReturnCode l_rc; + errlHndl_t l_errl = nullptr; + TARGETING::Target * l_sysTarget = nullptr; + TARGETING::ATTR_FREQ_OMI_MHZ_type l_omiFreq = 0; + TARGETING::ATTR_OMI_PLL_VCO_type l_omiVco = 0; + bool l_matchFound = false; + + // There can be up to 2 matches for OMI frequencies. If only 1 match is found + // then we ignore the VCO attribute + std::vector<OmiFreqVcoBucketSelect_t> l_omiFreqMatches; + + do{ + // Convert to platform-style target + l_errl = getTargetingTarget(i_fapiTarget, l_sysTarget); + + if(l_errl) + { + FAPI_ERR("platGetMcPllBucket: Error from getTargetingTarget"); + l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_errl)); + break; + } + + // Use helper function to lookup omi frequency and omi vco for this system + l_errl = getOmiFreqAndVco(l_omiFreq, l_omiVco); + + if(l_errl) + { + l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_errl)); + break; + } + + // Loop through the MEM_PLL frequency buckets to see if we can find a bucket that + // matches what we have found for omi freq and vco + for(uint8_t i = 0; i < MEM_PLL_FREQ_BUCKETS; i++) + { + if(OMI_PLL_FREQ_LIST[i].omifreq == l_omiFreq) + { + OmiFreqVcoBucketSelect_t l_tmpBucketSelect = {OMI_PLL_FREQ_LIST[i].omifreq, OMI_PLL_FREQ_LIST[i].vco, i}; + l_omiFreqMatches.push_back(l_tmpBucketSelect); + } + } + + if(l_omiFreqMatches.size() > 1) + { + for(uint8_t i = 0; i < l_omiFreqMatches.size(); i++) + { + if(l_omiFreqMatches[i].vco == l_omiVco) + { + FAPI_INF("Found match to be bucket %d for freq %d, vco %d", + l_omiFreqMatches[i].pll_bucket, + OMI_PLL_FREQ_LIST[i].omifreq, + OMI_PLL_FREQ_LIST[i].vco); + l_matchFound = true; + // Value returned in this case is the bucket number that had the matching values + // MC_PLL_BUCKET attribute is 1-based so increment bucket ID by 1 + o_val = l_omiFreqMatches[i].pll_bucket + 1; + break; + } + } + } + else if (l_omiFreqMatches.size() == 1) + { + FAPI_INF("Single match for OMI freq %d found in OMI_PLL_FREQ_LIST, ignoring VCO attribute. PLL Bucket = %d", + l_omiFreq, + l_omiFreqMatches[0].pll_bucket); + l_matchFound = true; + // MC_PLL_BUCKET attribute is 1-based so increment bucket ID by 1 + o_val = l_omiFreqMatches[0].pll_bucket + 1; + } + + // If not match is found return an error + if(!l_matchFound) + { + FAPI_ERR("platGetMcPllBucket: Could not find matching bucket for omiFreq = %d and vco = %d", + l_omiFreq, l_omiVco); + + /*@ + * @errortype + * @moduleid fapi2::MOD_FAPI2_PLAT_GET_MC_PLL_BUCKET + * @reasoncode fapi2::RC_NO_MATCHING_FREQ + * @userdata1[0:31] ATTR_FREQ_OMI_MHZ + * @userdata1[32:63] ATTR_FREQ_PLL_VCO + * @userdata2 Target HUID + * @devdesc Invalid omi frequence and omi vco settings + */ + l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + fapi2::MOD_FAPI2_PLAT_GET_MC_PLL_BUCKET, + fapi2::RC_NO_MATCHING_FREQ, + TWO_UINT32_TO_UINT64(l_omiFreq, l_omiVco), + TARGETING::get_huid(l_sysTarget), + ERRORLOG::ErrlEntry::NO_SW_CALLOUT); + l_errl->collectTrace(FAPI_IMP_TRACE_NAME, 256); + l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_errl)); + break; + } + + }while(0); + return l_rc; +} + +//****************************************************************************** +// fapi::platAttrSvc::platGetFreqMcaMhz function +//****************************************************************************** +ReturnCode platGetFreqMcaMhz(const Target<TARGET_TYPE_ALL>& i_fapiTarget, + ATTR_FREQ_MCA_MHZ_Type & o_val) +{ + fapi2::ReturnCode l_rc; + errlHndl_t l_errl = nullptr; + TARGETING::Target * l_sysTarget = nullptr; + TARGETING::ATTR_FREQ_OMI_MHZ_type l_omiFreq = 0; + TARGETING::ATTR_OMI_PLL_VCO_type l_omiVco = 0; + bool l_matchFound = false; + + // There can be up to 2 matches for OMI frequencies. If only 1 match is found + // then we ignore the VCO attribute + std::vector<OmiBucketDescriptor_t> l_matchingOmiBucketDescriptors; + + do{ + // Convert to platform-style target + l_errl = getTargetingTarget(i_fapiTarget, l_sysTarget); + + if(l_errl) + { + FAPI_ERR("platGetFreqMcaMhz: Error from getTargetingTarget"); + l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_errl)); + break; + } + + // Use helper function to lookup omi frequency and omi vco for this system + l_errl = getOmiFreqAndVco(l_omiFreq, l_omiVco); + + if(l_errl) + { + l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_errl)); + break; + } + + // Loop through the MEM_PLL frequency buckets to see if we can find a bucket that + // matches what we have found for omi freq and vco + for(uint8_t i = 0; i < MEM_PLL_FREQ_BUCKETS; i++) + { + if(OMI_PLL_FREQ_LIST[i].omifreq == l_omiFreq) + { + l_matchingOmiBucketDescriptors.push_back(OMI_PLL_FREQ_LIST[i]); + } + } + + if(l_matchingOmiBucketDescriptors.size() > 1) + { + for(uint8_t i = 0; i < l_matchingOmiBucketDescriptors.size(); i++) + { + if(l_matchingOmiBucketDescriptors[i].vco == l_omiVco) + { + FAPI_INF("found match for freq %d, vco %d. Mca freq = %d", + OMI_PLL_FREQ_LIST[i].omifreq, OMI_PLL_FREQ_LIST[i].vco); + l_matchFound = true; + // Value returned in this case is the bucket number that had the matching values + o_val = l_matchingOmiBucketDescriptors[i].mcafreq; + break; + } + } + } + else if (l_matchingOmiBucketDescriptors.size() == 1) + { + FAPI_INF("Single match for OMI freq %d found in OMI_PLL_FREQ_LIST, MCA freq found = %d, ignoring VCO attribute", + l_omiFreq, + l_matchingOmiBucketDescriptors[0].mcafreq); + l_matchFound = true; + o_val = l_matchingOmiBucketDescriptors[0].mcafreq; + } + + if(!l_matchFound) + { + FAPI_ERR("platGetFreqMcaMhz: Could not find matching bucket for omiFreq = %d and vco = %d", + l_omiFreq, l_omiVco); + + /*@ + * @errortype + * @moduleid fapi2::MOD_FAPI2_PLAT_GET_FREQ_MCA_MHZ + * @reasoncode fapi2::RC_NO_MATCHING_FREQ + * @userdata1[0:31] ATTR_FREQ_OMI_MHZ + * @userdata1[32:63] ATTR_FREQ_PLL_VCO + * @userdata2 Target HUID + * @devdesc Invalid omi frequence and omi vco settings + */ + l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + fapi2::MOD_FAPI2_PLAT_GET_FREQ_MCA_MHZ, + fapi2::RC_NO_MATCHING_FREQ, + TWO_UINT32_TO_UINT64(l_omiFreq, l_omiVco), + TARGETING::get_huid(l_sysTarget), + ERRORLOG::ErrlEntry::NO_SW_CALLOUT); + l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_errl)); + break; + } + + }while(0); + return l_rc; +} + + + +#endif + +//****************************************************************************** +// fapi::platAttrSvc::platIncrementCounter function +//****************************************************************************** +ReturnCode platIncrementOcmbCounter(const Target<TARGET_TYPE_ALL>& i_fapiTarget, + uint32_t & o_val) +{ + fapi2::ReturnCode rc; + errlHndl_t l_errl = nullptr; + + TARGETING::Target * l_chipTarget = nullptr; + static mutex_t l_counter_mutex = MUTEX_INITIALIZER; + l_errl = getTargetingTarget(i_fapiTarget, l_chipTarget); + if (l_errl) + { + FAPI_ERR("platIncrementOcmbCounter: Error from getTargetingTarget"); + rc.setPlatDataPtr(reinterpret_cast<void *> (l_errl)); + } + else + { + mutex_lock(&l_counter_mutex); + o_val = l_chipTarget->getAttr<TARGETING::ATTR_OCMB_COUNTER_HB>(); + if( o_val == 0 ) + { + // seed each target with a unique number to make messages more + // distinct across operations + o_val = (l_chipTarget->getAttr<TARGETING::ATTR_HUID>() + && 0x0000FFFF) << 16; + } + else + { + ++o_val; + } + l_chipTarget->setAttr<TARGETING::ATTR_OCMB_COUNTER_HB>(o_val); + mutex_unlock(&l_counter_mutex); + } + return rc; +} } // End platAttrSvc namespace } // End fapi2 namespace diff --git a/src/usr/fapi2/dimmBadDqBitmapFuncs.C b/src/usr/fapi2/dimmBadDqBitmapFuncs.C index 8fb4b9fe0..170c022c5 100644 --- a/src/usr/fapi2/dimmBadDqBitmapFuncs.C +++ b/src/usr/fapi2/dimmBadDqBitmapFuncs.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2017,2018 */ +/* Contributors Listed Below - COPYRIGHT 2017,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -38,8 +38,8 @@ extern "C" // Utility function to check parameters and get the Bad DQ bitmap //------------------------------------------------------------------------------ fapi2::ReturnCode dimmBadDqCheckParamGetBitmap( const fapi2::Target - <fapi2::TARGET_TYPE_MCA|fapi2::TARGET_TYPE_MBA|fapi2::TARGET_TYPE_MEM_PORT> - & i_fapiTrgt, + <fapi2::TARGET_TYPE_MCA|fapi2::TARGET_TYPE_MBA| + fapi2::TARGET_TYPE_MEM_PORT|fapi2::TARGET_TYPE_OCMB_CHIP> & i_fapiTrgt, const uint8_t i_port, const uint8_t i_dimm, const uint8_t i_rank, @@ -115,8 +115,8 @@ fapi2::ReturnCode dimmBadDqCheckParamGetBitmap( const fapi2::Target //------------------------------------------------------------------------------ fapi2::ReturnCode p9DimmGetBadDqBitmap( const fapi2::Target - <fapi2::TARGET_TYPE_MCA|fapi2::TARGET_TYPE_MBA|fapi2::TARGET_TYPE_MEM_PORT> - & i_fapiTrgt, + <fapi2::TARGET_TYPE_MCA|fapi2::TARGET_TYPE_MBA| + fapi2::TARGET_TYPE_MEM_PORT|fapi2::TARGET_TYPE_OCMB_CHIP> & i_fapiTrgt, const uint8_t i_dimm, const uint8_t i_rank, uint8_t (&o_data)[mss::BAD_DQ_BYTE_COUNT], @@ -151,8 +151,8 @@ fapi2::ReturnCode p9DimmGetBadDqBitmap( const fapi2::Target //------------------------------------------------------------------------------ fapi2::ReturnCode p9DimmSetBadDqBitmap( const fapi2::Target - <fapi2::TARGET_TYPE_MCA|fapi2::TARGET_TYPE_MBA|fapi2::TARGET_TYPE_MEM_PORT> - & i_fapiTrgt, + <fapi2::TARGET_TYPE_MCA|fapi2::TARGET_TYPE_MBA| + fapi2::TARGET_TYPE_MEM_PORT|fapi2::TARGET_TYPE_OCMB_CHIP> & i_fapiTrgt, const uint8_t i_dimm, const uint8_t i_rank, const uint8_t (&i_data)[mss::BAD_DQ_BYTE_COUNT], @@ -179,17 +179,8 @@ fapi2::ReturnCode p9DimmSetBadDqBitmap( const fapi2::Target // Add the rank bitmap to the DIMM bitmap and write the bitmap. memcpy( l_dqBitmap[i_rank], i_data, mss::BAD_DQ_BYTE_COUNT ); - errlHndl_t l_errl = nullptr; - TARGETING::TargetHandle_t l_trgt = nullptr; - l_errl = fapi2::platAttrSvc::getTargetingTarget(i_fapiTrgt, l_trgt); - if ( l_errl ) - { - FAPI_ERR( "p9DimmSetBadDqBitmap: Error from getTargetingTarget" ); - break; - } - l_rc = FAPI_ATTR_SET( fapi2::ATTR_BAD_DQ_BITMAP, l_dimmTrgt, - l_dqBitmap ); + l_dqBitmap ); if ( l_rc ) { diff --git a/src/usr/fapi2/fapi2.mk b/src/usr/fapi2/fapi2.mk index c69d77c92..713e3e80b 100755 --- a/src/usr/fapi2/fapi2.mk +++ b/src/usr/fapi2/fapi2.mk @@ -59,6 +59,10 @@ EXTRAINCDIR += ${HWP_PATH_2}/hwp/memory/lib/shared/ EXTRAINCDIR += ${HWP_PATH_2}/hwp/memory/lib/utils/ EXTRAINCDIR += ${HWP_PATH_2}/vpd_accessors/ EXTRAINCDIR += ${ROOTPATH}/src/usr/scom/ +EXTRAINCDIR += ${ROOTPATH}/src/import/chips/ocmb/explorer/common/include/ +EXTRAINCDIR += ${ROOTPATH}/src/import/chips/common/utils/ +EXTRAINCDIR += ${ROOTPATH}/src/import/chips/p9/common/include/ +EXTRAINCDIR += ${ROOTPATH}/src/import/chips/ocmb/explorer/procedures/hwp/memory/ include ${ROOTPATH}/src/build/mkrules/verbose.rules.mk define __CLEAN_TARGET @@ -128,6 +132,10 @@ FAPI2_ERROR_XML += $(wildcard \ $(ROOTPATH)/src/import/chips/ocmb/explorer/procedures/xml/error_info/*.xml) FAPI2_ERROR_XML += $(wildcard \ $(ROOTPATH)/src/import/chips/p9a/procedures/xml/error_info/*.xml) +FAPI2_ERROR_XML += $(wildcard \ + $(ROOTPATH)/src/import/chips/ocmb/gemini/procedures/xml/error_info/*.xml) +FAPI2_ERROR_XML += $(wildcard \ + $(ROOTPATH)/src/import/chips/ocmb/common/procedures/xml/error_info/*.xml) # Attribute XML files. FAPI2_ATTR_XML += $(wildcard \ @@ -140,6 +148,10 @@ FAPI2_ATTR_XML += $(wildcard \ $(ROOTPATH)/src/import/generic/procedures/xml/attribute_info/*.xml) FAPI2_ATTR_XML += $(wildcard \ $(ROOTPATH)/src/import/chips/ocmb/explorer/procedures/xml/attribute_info/*.xml) +FAPI2_ATTR_XML += $(wildcard \ + $(ROOTPATH)/src/import/chips/ocmb/gemini/procedures/xml/attribute_info/*.xml) +FAPI2_ATTR_XML += $(wildcard \ + $(ROOTPATH)/src/import/chips/ocmb/common/procedures/xml/attribute_info/*.xml) # Filter out Temp defaults XML file from Attribute XML files. # NOTE: The hb_temp_defaults.xml file is not a normal attribute file with the diff --git a/src/usr/fapi2/platCreateHwpErrParser.pl b/src/usr/fapi2/platCreateHwpErrParser.pl index 618459e30..84fc84316 100755 --- a/src/usr/fapi2/platCreateHwpErrParser.pl +++ b/src/usr/fapi2/platCreateHwpErrParser.pl @@ -6,9 +6,10 @@ # # OpenPOWER HostBoot Project # -# Contributors Listed Below - COPYRIGHT 2015,2018 +# Contributors Listed Below - COPYRIGHT 2015,2019 # [+] Google Inc. # [+] International Business Machines Corp. +# [+] YADRO # # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -78,13 +79,14 @@ print TGFILE "// This file is generated by perl script platCreateHwpErrParser.pl print TGFILE "#ifndef HBFWPLATHWPERRPARSER_H_\n"; print TGFILE "#define HBFWPLATHWPERRPARSER_H_\n\n"; print TGFILE "#if defined(PARSER) || defined(LOGPARSER)\n\n"; +print TGFILE "#include \"errluserdetails.H\"\n\n"; print TGFILE "namespace fapi2\n"; print TGFILE "{\n\n"; print TGFILE "void hbfwParseHwpRc(ErrlUsrParser & i_parser,\n"; print TGFILE " void * i_pBuffer,\n"; print TGFILE " const uint32_t i_buflen)\n"; print TGFILE "{\n"; -print TGFILE " uint32_t l_rc = ntohl(*(static_cast<uint32_t *>(i_pBuffer)));\n"; +print TGFILE " uint32_t l_rc = ntohl(ERRORLOG::UINT32_FROM_PTR(i_pBuffer));\n"; print TGFILE " switch(l_rc)\n"; print TGFILE " {\n"; @@ -225,6 +227,7 @@ print EDISFILE "#include <p9_perv_scom_addresses.H>\n"; print EDISFILE "#include <p9_quad_scom_addresses.H>\n"; print EDISFILE "#include <p9_xbus_scom_addresses.H>\n"; print EDISFILE "#include <cen_gen_scom_addresses.H>\n"; +print EDISFILE "#include <explorer_scom_addresses.H>\n"; print EDISFILE "#include <centaur_misc_constants.H>\n"; print EDISFILE "namespace fapi2\n"; print EDISFILE "{\n\n"; @@ -243,7 +246,7 @@ print TGFILE " uint8_t * l_pBuffer = static_cast<uint8_t *>(i_pBuffer);\n"; print TGFILE " uint32_t l_buflen = i_buflen;\n\n"; print TGFILE " // The first uint32_t is the FFDC ID\n"; print TGFILE " uint32_t * l_pFfdcId = static_cast<uint32_t *>(i_pBuffer);\n"; -print TGFILE " uint32_t l_ffdcId = ntohl(*l_pFfdcId);\n"; +print TGFILE " uint32_t l_ffdcId = ntohl(ERRORLOG::UINT32_FROM_PTR(l_pFfdcId));\n"; print TGFILE " l_pBuffer += sizeof(l_ffdcId);\n"; print TGFILE " l_buflen -= sizeof(l_ffdcId);\n"; print TGFILE " switch(l_ffdcId)\n"; @@ -364,7 +367,7 @@ foreach my $argnum (1 .. $#ARGV) print TGFILE " if (l_buflen >= POS_LEN)\n"; print TGFILE " {\n"; print TGFILE " uint32_t * l_pBufferTemp = reinterpret_cast<uint32_t *>(l_pBuffer);\n"; - print TGFILE " i_parser.PrintNumber(\"Chip Position:\",\"%X\",ntohl(*l_pBufferTemp));\n"; + print TGFILE " i_parser.PrintNumber(\"Chip Position:\",\"%X\",ntohl(ERRORLOG::UINT32_FROM_PTR(l_pBufferTemp)));\n"; print TGFILE " l_pBufferTemp = NULL;\n"; print TGFILE " l_pBuffer+= POS_LEN;\n"; print TGFILE " l_buflen -= POS_LEN;\n"; diff --git a/src/usr/fapi2/plat_mmio_access.C b/src/usr/fapi2/plat_mmio_access.C index 60526761b..365aa1f22 100644 --- a/src/usr/fapi2/plat_mmio_access.C +++ b/src/usr/fapi2/plat_mmio_access.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2018 */ +/* Contributors Listed Below - COPYRIGHT 2018,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -39,9 +39,272 @@ #include <hwpf_fapi2_reasoncodes.H> #include <fapi2/plat_mmio_access.H> - namespace fapi2 { +// Address bit that designates it as an Explorer MMIO address +static const uint64_t EXPLR_IB_MMIO_OFFSET = 0x0000000100000000ull; + +// Valid I2C access to 256MB SRAM space, starts at offset 0x01000000 +static const uint64_t MIN_I2C_SRAM_SPACE_ADDRESS = 0x0000000001000000ull; +static const uint64_t MAX_I2C_SRAM_SPACE_ADDRESS = 0x0000000001030000ull; + +// byte transaction sizes for i2c +static const size_t I2C_TRANSACTION_SIZE = 4; // actual size sent +static const size_t SCOM_I2C_TRANSACTION_SIZE = 8; + +// Convert MMIO to I2C address (need these bits set) +static const uint64_t EXPLR_MMIO_TO_I2C_ADDRESS_MASK = 0xA0000000; + + +/** + * @brief Explorer Inband read via i2c + * @param[in] i_target - OCMB target + * @param[in/out] io_data_read - buffer to be filled with read data + * @param[in/out] io_get_size - size of buffer (returns read size) + * @param[in] i_i2c_addr - i2c scom address + * @return errlHndl_t indicating success or failure + */ +errlHndl_t explrIbI2cRead(TARGETING::Target * i_target, + uint8_t * io_data_read, + size_t io_get_size, + const uint64_t i_i2c_addr) +{ + errlHndl_t l_err = nullptr; + + if ( io_get_size % I2C_TRANSACTION_SIZE ) + { + // invalid size expected (needs to be a multiple of I2C_TRANSACTION_SIZE) + FAPI_ERR("explrIbI2cRead: read size %d is not a multiple of %d", + io_get_size, I2C_TRANSACTION_SIZE); + /*@ + * @errortype + * @moduleid fapi2::MOD_FAPI2_EXPLR_IB_I2C_READ + * @reasoncode fapi2::RC_INVALID_BUFFER_SIZE + * @userdata1[0:31] Buffer size + * @userdata1[32:63] Transaction size + * @userdata2[0:31] HUID of input target + * @userdata2[32:63] i2c_address + * @devdesc Invalid read buffer size, needs to be divisible by transaction size + * @custdesc Internal firmware error + */ + l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + fapi2::MOD_FAPI2_EXPLR_IB_I2C_READ, + fapi2::RC_INVALID_BUFFER_SIZE, + TWO_UINT32_TO_UINT64(io_get_size, + I2C_TRANSACTION_SIZE), + TWO_UINT32_TO_UINT64( + TARGETING::get_huid(i_target), + i_i2c_addr), + ERRORLOG::ErrlEntry::ADD_SW_CALLOUT); + l_err->collectTrace(FAPI_TRACE_NAME); + io_get_size = 0; // no data being read + } + else + { + FAPI_INF("explrIbI2cRead: deviceRead() starting at i2cscom address " + "0x%08X for %d bytes", i_i2c_addr, io_get_size); + + // keep track of total bytes read + size_t total_bytes_read = 0; + + // Increment this address after each read transaction + uint64_t i2cAddr = i_i2c_addr; + + // scom transaction variables + size_t scomTransSize = SCOM_I2C_TRANSACTION_SIZE; + uint8_t scomReadData[SCOM_I2C_TRANSACTION_SIZE]; + + // Only able to read 4 bytes at a time with i2c, so + // need to break into multiple i2c read transactions + while( total_bytes_read < io_get_size ) + { + FAPI_DBG("explrIbI2cRead: deviceRead() at i2cscom address 0x%08X", i2cAddr); + l_err = deviceOp( DeviceFW::READ, + i_target, + scomReadData, + scomTransSize, + DEVICE_I2CSCOM_ADDRESS(i2cAddr) ); + if (l_err) + { + FAPI_ERR("explrIbI2cRead: target 0x%08X deviceRead() at address 0x%08X failed", + TARGETING::get_huid(i_target), i2cAddr); + l_err->collectTrace(FAPI_TRACE_NAME); + break; + } + else + { + FAPI_DBG("explrIbI2cRead: read %02X%02X%02X%02X", + scomReadData[4], scomReadData[5], scomReadData[6], scomReadData[7]); + } + + // The MMIO hardware does this byteswap for us, since we are + // running this over i2c we must reorder the bytes here + io_data_read[total_bytes_read] = scomReadData[7]; + io_data_read[total_bytes_read+1] = scomReadData[6]; + io_data_read[total_bytes_read+2] = scomReadData[5]; + io_data_read[total_bytes_read+3] = scomReadData[4]; + + // Only able to read 4 bytes at a time + total_bytes_read += I2C_TRANSACTION_SIZE; + i2cAddr += I2C_TRANSACTION_SIZE; + + // make sure this value is correct for next op + scomTransSize = SCOM_I2C_TRANSACTION_SIZE; + } + } + return l_err; +} + + +/** + * @brief Explorer Inband write via i2c + * @param[in] i_target - OCMB target + * @param[in] i_write_data - data to write out + * @param[in/out] io_write_size - how much data to write (returns how much written) + * @param[in] i_i2c_addr - i2c scom address + * @return errlHndl_t indicating success or failure + */ +errlHndl_t explrIbI2cWrite(TARGETING::Target * i_target, + const uint8_t * i_write_data, + size_t io_write_size, + const uint64_t i_i2c_addr) +{ + errlHndl_t l_err = nullptr; + + // Verify write can be divide up evenly + if ( io_write_size % I2C_TRANSACTION_SIZE ) + { + // invalid size expected (needs to be a multiple of I2C_TRANSACTION_SIZE) + FAPI_ERR("explrIbI2cWrite: write size %d is not a multiple of %d", + io_write_size, I2C_TRANSACTION_SIZE); + /*@ + * @errortype + * @moduleid fapi2::MOD_FAPI2_EXPLR_IB_I2C_WRITE + * @reasoncode fapi2::RC_INVALID_BUFFER_SIZE + * @userdata1[0:31] Buffer size + * @userdata1[32:63] Transaction size + * @userdata2[0:31] HUID of input target + * @userdata2[32:63] i2c_address + * @devdesc Invalid write buffer size, needs to be divisible by transaction size + * @custdesc Internal firmware error + */ + l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + fapi2::MOD_FAPI2_EXPLR_IB_I2C_READ, + fapi2::RC_INVALID_BUFFER_SIZE, + TWO_UINT32_TO_UINT64(io_write_size, + I2C_TRANSACTION_SIZE), + TWO_UINT32_TO_UINT64( + TARGETING::get_huid(i_target), + i_i2c_addr), + ERRORLOG::ErrlEntry::ADD_SW_CALLOUT); + l_err->collectTrace(FAPI_TRACE_NAME); + } + else + { + // counter for bytes written out to SRAM space + size_t total_bytes_written = 0; + + // going to alter this address to cycle through write data + uint64_t i2cAddr = i_i2c_addr; + + // scom transaction variables + size_t scomTransSize = SCOM_I2C_TRANSACTION_SIZE; + uint8_t scomWriteData[SCOM_I2C_TRANSACTION_SIZE]; + + FAPI_INF("explrIbI2cWrite: deviceWrite() starting at i2cscom address " + "0x%08X for %d bytes", i_i2c_addr, io_write_size); + + // Only able to write 4 bytes at a time with i2c, + // so need to break into multiple i2c write transactions + while( total_bytes_written < io_write_size ) + { + memset(scomWriteData, 0x00, SCOM_I2C_TRANSACTION_SIZE); + + // Only last four bytes are actually written out + // NOTE: MMIO hardware does this byteswap for us, but since we + // are running this over i2c we must reorder the bytes here + scomWriteData[7] = i_write_data[total_bytes_written]; + scomWriteData[6] = i_write_data[total_bytes_written+1]; + scomWriteData[5] = i_write_data[total_bytes_written+2]; + scomWriteData[4] = i_write_data[total_bytes_written+3]; + + l_err = deviceOp( DeviceFW::WRITE, + i_target, + scomWriteData, + scomTransSize, + DEVICE_I2CSCOM_ADDRESS(i2cAddr) ); + if (l_err) + { + FAPI_ERR("explrIbI2cWrite: i2cscom write(0x%02X%02X%02X%02X) at address 0x%08X failed", + scomWriteData[4], scomWriteData[5], scomWriteData[6], scomWriteData[7], i2cAddr); + l_err->collectTrace(FAPI_TRACE_NAME); + break; + } + // Really only doing 4-byte transactions + i2cAddr += I2C_TRANSACTION_SIZE; + total_bytes_written += I2C_TRANSACTION_SIZE; + + // Update for next scom operation + scomTransSize = SCOM_I2C_TRANSACTION_SIZE; + } + } + return l_err; +} + +/** + * @brief Checks if all the conditions are met to allow i2c + * operation instead of MMIO. + * @param[in] i_ocmb - OCMB target + * @param[in] i_mmioAddress - address passed into get/putMMIO + * @return true if i2c should be used instead of MMIO + */ +bool useI2cInsteadOfMmio( const TARGETING::Target * i_ocmb, + const uint64_t i_mmioAddress ) +{ + bool useI2c = false; // default to use MMIO + + uint8_t attrAllowedI2c = 0; + + // Check force i2c attribute first + TARGETING::Target* l_sys = nullptr; + TARGETING::targetService().getTopLevelTarget(l_sys); + crit_assert(l_sys != nullptr); + attrAllowedI2c = l_sys->getAttr<TARGETING::ATTR_FORCE_SRAM_MMIO_OVER_I2C>(); + + // If not forced to use i2c, then check if that is the current scom setting + if (!attrAllowedI2c) + { + // The SCOM_SWITCHES attribute will keep track of when it is safe + // to access the ocmb via inband vs when we should do accesses over + // i2c. Use this attribute to decide which we want to use. + auto ocmb_info = i_ocmb->getAttr<TARGETING::ATTR_SCOM_SWITCHES>(); + if (!ocmb_info.useInbandScom) + { + attrAllowedI2c = 1; + } + } + + // Attribute settings must allow i2c operation before checking + // for a valid address range + if (attrAllowedI2c) + { + // Verify address is within valid SRAM range + if ( ((i_mmioAddress & 0x0F00000000) == EXPLR_IB_MMIO_OFFSET) && + ((i_mmioAddress & 0x0FFFFFFFF) >= MIN_I2C_SRAM_SPACE_ADDRESS) && + ((i_mmioAddress & 0x0FFFFFFFF) <= MAX_I2C_SRAM_SPACE_ADDRESS) ) + { + useI2c = true; + } + else + { + FAPI_INF("0x%08X OCMB address 0x%.8X is outside of SRAM range so using mmio", + TARGETING::get_huid(i_ocmb), i_mmioAddress); + } + } + + return useI2c; +} + //------------------------------------------------------------------------------ // HW Communication Functions to be implemented at the platform layer. //------------------------------------------------------------------------------ @@ -83,12 +346,22 @@ ReturnCode platGetMMIO( const Target<TARGET_TYPE_ALL>& i_target, break; //return with error } - // call MMIO driver - l_err = DeviceFW::deviceRead(l_target, - l_data_read, - l_get_size, - DEVICE_MMIO_ADDRESS(i_mmioAddr, i_transSize)); - + // Run mmio if inband i2c isn't enabled or address is outside of SRAM range + if ( !useI2cInsteadOfMmio(l_target, i_mmioAddr) ) + { + // call MMIO driver + l_err = DeviceFW::deviceRead(l_target, + l_data_read, + l_get_size, + DEVICE_MMIO_ADDRESS(i_mmioAddr, i_transSize)); + } + else + { + // Use i2c instead of MMMIO + // Explorer i2c addresses are actually 32-bit and need 0xA at the beginning + uint64_t i2cAddr = (i_mmioAddr & 0x00000000FFFFFFFF) | EXPLR_MMIO_TO_I2C_ADDRESS_MASK; + l_err = explrIbI2cRead(l_target, l_data_read, l_get_size, i2cAddr); + } if (l_traceit) { // Only trace the first 8 bytes of data read @@ -167,11 +440,22 @@ ReturnCode platPutMMIO( const Target<TARGET_TYPE_ALL>& i_target, std::copy(i_data.begin(), i_data.end(), l_writeDataPtr); size_t l_dataSize = i_data.size(); - // call MMIO driver - l_err = DeviceFW::deviceWrite(l_target, - l_writeDataPtr, - l_dataSize, - DEVICE_MMIO_ADDRESS(i_mmioAddr, i_transSize)); + // Run mmio if inband i2c isn't enabled or address is outside of SRAM range + if ( !useI2cInsteadOfMmio(l_target, i_mmioAddr) ) + { + // call MMIO driver + l_err = DeviceFW::deviceWrite(l_target, + l_writeDataPtr, + l_dataSize, + DEVICE_MMIO_ADDRESS(i_mmioAddr, i_transSize)); + } + else + { + // Address is an Explorer SRAM address, so I2C will work + // Explorer i2c addresses are actually 32-bit and need 0xA at the beginning + uint64_t i2cAddr = (i_mmioAddr & 0x00000000FFFFFFFF) | EXPLR_MMIO_TO_I2C_ADDRESS_MASK; + l_err = explrIbI2cWrite(l_target, l_writeDataPtr, l_dataSize, i2cAddr); + } if (l_traceit) { // trace the first 8 bytes of written data diff --git a/src/usr/fapi2/plat_spd_access.C b/src/usr/fapi2/plat_spd_access.C index c8466f5da..6f3107f0c 100644 --- a/src/usr/fapi2/plat_spd_access.C +++ b/src/usr/fapi2/plat_spd_access.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* Contributors Listed Below - COPYRIGHT 2015,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -34,6 +34,8 @@ #include <errl/errlentry.H> #include <errl/errlmanager.H> #include <fapi2_spd_access.H> +#include <vpd/spdenums.H> +#include <hwas/common/hwasCallout.H> namespace fapi2 { @@ -49,14 +51,9 @@ fapi2::ReturnCode getSPD( { FAPI_DBG(ENTER_MRK "getSPD"); - const uint8_t MEM_DDR3 = 0xB; - const uint8_t MEM_DDR4 = 0xC; - const uint32_t DDR3_KEYWORD_SIZE = 256; - const uint32_t DDR4_KEYWORD_SIZE = 512; - - errlHndl_t l_errl = NULL; + errlHndl_t l_errl = nullptr; fapi2::ReturnCode l_rc; - TARGETING::Target* l_pTarget = NULL; + TARGETING::Target* l_pTarget = nullptr; do { @@ -65,49 +62,104 @@ fapi2::ReturnCode getSPD( TARGETING::TYPE_DIMM); if (l_errl) { - FAPI_ERR("getSPD: Error from getTargetingTarget"); + FAPI_ERR("getSPD: Error from getTargetingTarget for TYPE_DIMM"); break; } // If the caller passed a nullptr for blob then // return size of the SPD - if ( o_blob == NULL ) + if ( o_blob == nullptr ) { - // Get the DDR device type from SPD - uint8_t l_memType = 0x0; - size_t l_memSize = sizeof(l_memType); + // Get the DRAM generation from SPD + uint8_t l_memGen = 0x0; + size_t l_memSize = sizeof(l_memGen); l_errl = deviceRead(l_pTarget, - (void *)&l_memType, - l_memSize, - DEVICE_SPD_ADDRESS(SPD::BASIC_MEMORY_TYPE)); + static_cast<void *>(&l_memGen), + l_memSize, + DEVICE_SPD_ADDRESS(SPD::BASIC_MEMORY_TYPE)); + + if ( l_errl ) + { + FAPI_ERR("getSPD: Error from deviceRead for BASIC_MEMORY_TYPE") + break; + } - if ( !l_errl ) + switch(l_memGen) { - if ( l_memType == MEM_DDR3 ) + case SPD::MEM_DDR3: + o_size = SPD::DDR3_SPD_SIZE; + break; + + case SPD::MEM_DDR4: { - o_size = DDR3_KEYWORD_SIZE; - } - else if ( l_memType == MEM_DDR4 ) + uint8_t l_memModule = 0x0; + + l_errl = deviceRead(l_pTarget, + static_cast<void *>(&l_memModule), + l_memSize, + DEVICE_SPD_ADDRESS(SPD::MODULE_TYPE)); + + if( l_errl ) + { + FAPI_ERR("getSPD: Error on deviceRead for MODULE_TYPE"); + break; + } + + if( l_memModule == SPD::MEM_DDIMM ) + { + // currently getSPD only supports the ENTIRE_SPD + // keyword. In the DDIMM case this include the EFD + // data so be sure to reflect that in the size we return. + o_size = SPD::OCMB_SPD_EFD_COMBINED_SIZE; + } + else + { + o_size = SPD::DDR4_SPD_SIZE; + } + }// case MEM_DDR4 + break; + + default: { - o_size = DDR4_KEYWORD_SIZE; - } - else - { - FAPI_ERR("getSPD: Invalid DIMM DDR Type"); - break; + FAPI_ERR("getSPD: Unsupported DIMM DDR Generation"); + + /*@ + * @errortype + * @moduleid MOD_FAPI2_SPD_ACCESS + * @reasoncode RC_INVALID_SPD_DRAM_GEN + * @userdata1 DDR generation + * @userdata2 HUID of input target + * @devdesc Bad SPD or unsupported DIMM + * @custdesc Unsupported DIMM generation + */ + l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + MOD_FAPI2_SPD_ACCESS, + RC_INVALID_SPD_DRAM_GEN, + TARGETING::get_huid(l_pTarget), + l_memGen ); + + l_errl->addHwCallout( l_pTarget, + HWAS::SRCI_PRIORITY_HIGH, + HWAS::DELAYED_DECONFIG, + HWAS::GARD_NULL ); } + break; - FAPI_DBG("getSPD: Returning the size of the SPD :%d ", o_size); - } - } + }// switch + + FAPI_DBG("getSPD: Returning the size of the SPD :%d ", o_size); + + }// endif else { + // Return the entire SPD blob l_errl = deviceRead(l_pTarget, - o_blob, - o_size, - DEVICE_SPD_ADDRESS(SPD::ENTIRE_SPD)); - } + o_blob, + o_size, + DEVICE_SPD_ADDRESS(SPD::ENTIRE_SPD)); + }// end else break; @@ -118,7 +170,7 @@ fapi2::ReturnCode getSPD( FAPI_ERR("getSPD: Error getting SPD data for HUID=0x%.8X Size %d", TARGETING::get_huid(l_pTarget),o_size); - l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_errl)); + l_rc.setPlatDataPtr(reinterpret_cast<void *>(l_errl)); } FAPI_DBG("getSPD: SPD data for HUID=0x%.8X Size %d Blob %d", diff --git a/src/usr/fapi2/plat_utils.C b/src/usr/fapi2/plat_utils.C index 01eacb645..bcea30664 100644 --- a/src/usr/fapi2/plat_utils.C +++ b/src/usr/fapi2/plat_utils.C @@ -48,6 +48,7 @@ #include <p9_scan_compression.H> #include <cen_ringId.H> #include <scom/wakeup.H> +#include <util/misc.H> //****************************************************************************** // Trace descriptors @@ -941,6 +942,13 @@ void processEIBusCallouts(const ErrorInfo & i_errInfo, { l_busType = HWAS::DMI_BUS_TYPE; } + else if ( ((l_type1 == TARGETING::TYPE_DMI) && + (l_type2 == TARGETING::TYPE_MEMBUF)) || + ((l_type1 == TARGETING::TYPE_MEMBUF) && + (l_type2 == TARGETING::TYPE_DMI)) ) + { + l_busType = HWAS::DMI_BUS_TYPE; + } else if ((l_type1 == TARGETING::TYPE_ABUS) && (l_type2 == TARGETING::TYPE_ABUS)) { @@ -956,6 +964,13 @@ void processEIBusCallouts(const ErrorInfo & i_errInfo, { l_busType = HWAS::O_BUS_TYPE; } + else if ( ((l_type1 == TARGETING::TYPE_OMI) && + (l_type2 == TARGETING::TYPE_OCMB_CHIP)) || + ((l_type1 == TARGETING::TYPE_OCMB_CHIP) && + (l_type2 == TARGETING::TYPE_OMI)) ) + { + l_busType = HWAS::OMI_BUS_TYPE; + } else { FAPI_ERR("processEIBusCallouts: Bus between target types not known (0x%08x:0x%08x)", @@ -1468,7 +1483,12 @@ ReturnCode delay(uint64_t i_nanoSeconds, bool i_fixed) { //Note: i_fixed is deliberately ignored - nanosleep( 0, i_nanoSeconds ); + + // We don't need to waste time for hardware delays if we're running in Simics + if( !Util::isSimicsRunning() ) + { + nanosleep( 0, i_nanoSeconds ); + } return FAPI2_RC_SUCCESS; } diff --git a/src/usr/fapi2/rowRepairsFuncs.C b/src/usr/fapi2/rowRepairsFuncs.C index 6548e31ed..67796ad20 100644 --- a/src/usr/fapi2/rowRepairsFuncs.C +++ b/src/usr/fapi2/rowRepairsFuncs.C @@ -34,8 +34,8 @@ extern "C" { fapi2::ReturnCode __getDimmRepairData( const fapi2::Target - <fapi2::TARGET_TYPE_MCA|fapi2::TARGET_TYPE_MBA|fapi2::TARGET_TYPE_MEM_PORT> - & i_fapiTrgt, + <fapi2::TARGET_TYPE_MCA|fapi2::TARGET_TYPE_MBA| + fapi2::TARGET_TYPE_MEM_PORT|fapi2::TARGET_TYPE_OCMB_CHIP> & i_fapiTrgt, const uint8_t i_dimm, const uint8_t i_rank, TARGETING::TargetHandle_t & o_dimmTrgt, @@ -109,8 +109,8 @@ fapi2::ReturnCode __getDimmRepairData( const fapi2::Target //------------------------------------------------------------------------------ fapi2::ReturnCode getRowRepair( const fapi2::Target - <fapi2::TARGET_TYPE_MCA|fapi2::TARGET_TYPE_MBA|fapi2::TARGET_TYPE_MEM_PORT> - & i_fapiTrgt, + <fapi2::TARGET_TYPE_MCA|fapi2::TARGET_TYPE_MBA| + fapi2::TARGET_TYPE_MEM_PORT|fapi2::TARGET_TYPE_OCMB_CHIP> & i_fapiTrgt, const uint8_t i_dimm, const uint8_t i_rank, uint8_t (&o_data)[mss::ROW_REPAIR_BYTE_COUNT], @@ -147,8 +147,8 @@ fapi2::ReturnCode getRowRepair( const fapi2::Target //------------------------------------------------------------------------------ fapi2::ReturnCode setRowRepair( const fapi2::Target - <fapi2::TARGET_TYPE_MCA|fapi2::TARGET_TYPE_MBA|fapi2::TARGET_TYPE_MEM_PORT> - & i_fapiTrgt, + <fapi2::TARGET_TYPE_MCA|fapi2::TARGET_TYPE_MBA| + fapi2::TARGET_TYPE_MEM_PORT|fapi2::TARGET_TYPE_OCMB_CHIP> & i_fapiTrgt, const uint8_t i_dimm, const uint8_t i_rank, uint8_t (&i_data)[mss::ROW_REPAIR_BYTE_COUNT], diff --git a/src/usr/fapi2/test/fapi2DdimmGetEfdTest.C b/src/usr/fapi2/test/fapi2DdimmGetEfdTest.C index 13f0ed87b..400ca2a59 100644 --- a/src/usr/fapi2/test/fapi2DdimmGetEfdTest.C +++ b/src/usr/fapi2/test/fapi2DdimmGetEfdTest.C @@ -111,7 +111,8 @@ fapi2DdimmGetEfdTest::fapi2DdimmGetEfdTest() { FAPI_INF(">> fapi2DdimmGetEfdTest"); - if(TARGETING::MODEL_AXONE != TARGETING::targetService().getProcessorModel()) + iv_attrModel = TARGETING::targetService().getProcessorModel(); + if(TARGETING::MODEL_AXONE != iv_attrModel) { FAPI_INF("<< fapi2DdimmGetEfdTest: This is not AXONE. " "Skipping AXONE tests."); diff --git a/src/usr/fapi2/test/fapi2GetChildrenTest.H b/src/usr/fapi2/test/fapi2GetChildrenTest.H index 3971c1270..961579e1f 100644 --- a/src/usr/fapi2/test/fapi2GetChildrenTest.H +++ b/src/usr/fapi2/test/fapi2GetChildrenTest.H @@ -32,7 +32,6 @@ #include <functional> #include <plat_utils.H> #include <error_scope.H> -#include <config.h> namespace fapi2 { @@ -66,7 +65,6 @@ void test_fapi2GetChildren() uint32_t l_targetHuid = 0xFFFFFFFF; uint32_t l_actualSize = 0; uint32_t l_expectedSize = 0; - errlHndl_t l_err = nullptr; int numTests = 0; int numFails = 0; @@ -225,7 +223,7 @@ void test_fapi2GetChildren() numTests++; if(l_actualSize != l_expectedSize) { - TS_FAIL("test_fapi2GetChildren:: OMIs per proc mismatch"); + TS_FAIL("test_fapi2GetChildren:: OMIs per proc mismatch. Actual size: %d, Expected size: %d", l_actualSize, l_expectedSize); numFails++; break; } @@ -611,17 +609,25 @@ void test_fapi2GetChildren() TARGET_STATE_PRESENT).size(); } }, // CAPP pervasive has 1 CAPP child - {PERV_CAPP_CUMULUS_CHILDREN, + {PERV_CAPP_AXONE_CHILDREN, [](TARGETING::ATTR_CHIP_UNIT_type i_unit) { return ((i_unit == CAPP0_RANGE) || (i_unit == CAPP1_RANGE));}, [](Target<fapi2::TARGET_TYPE_PERV>& i_perv) { return i_perv.getChildren<fapi2::TARGET_TYPE_CAPP>( TARGET_STATE_PRESENT).size(); } }, - // OBUS pervasive has 3 OBUS BRICK children - {PERV_OBUS_BRICK_CHILDREN, + // OBUS0,3 pervasive has 2 OBUS BRICK children + {PERV_OBUS_BRICK03_AXONE_CHILDREN, [](TARGETING::ATTR_CHIP_UNIT_type i_unit) - { return ((i_unit >= OBUS_LOW) && (i_unit <= OBUS_HIGH)); }, + { return ((i_unit == OBUS_LOW+0) || (i_unit == OBUS_LOW+3)); }, + [](Target<fapi2::TARGET_TYPE_PERV>& i_perv) + { return i_perv.getChildren<fapi2::TARGET_TYPE_OBUS_BRICK>( + TARGET_STATE_PRESENT).size(); } }, + + // OBUS1,2 pervasive has 1 OBUS BRICK child + {PERV_OBUS_BRICK12_AXONE_CHILDREN, + [](TARGETING::ATTR_CHIP_UNIT_type i_unit) + { return ((i_unit == OBUS_LOW+1) || (i_unit == OBUS_LOW+2)); }, [](Target<fapi2::TARGET_TYPE_PERV>& i_perv) { return i_perv.getChildren<fapi2::TARGET_TYPE_OBUS_BRICK>( TARGET_STATE_PRESENT).size(); } }, @@ -699,7 +705,7 @@ void test_fapi2GetChildren() TARGET_STATE_PRESENT).size(); } }, }; - pervasiveChildTestRec* ptr; + pervasiveChildTestRec* ptr = nullptr; int numPervTests = 0; TARGETING::ATTR_MODEL_type l_model = l_proc->getAttr<TARGETING::ATTR_MODEL>(); if (l_model == TARGETING::MODEL_NIMBUS) @@ -750,9 +756,9 @@ void test_fapi2GetChildren() if(candidateTarget == nullptr) { - TS_FAIL("test_fapi2GetChildren:: candidateTarget not found"); + TS_FAIL("test_fapi2GetChildren:: candidateTarget not found - test %d", i); numFails++; - break; + continue; } l_targetHuid = TARGETING::get_huid(candidateTarget); @@ -764,9 +770,9 @@ void test_fapi2GetChildren() if(l_actualSize != l_expectedSize) { - TS_FAIL("test_fapi2GetChildren:: children of pervasive mismatch"); + TS_FAIL("test_fapi2GetChildren:: children of pervasive mismatch for %.8X (exp=%d,act=%d)", + l_targetHuid,l_expectedSize,l_actualSize); numFails++; - break; } } @@ -780,31 +786,6 @@ void test_fapi2GetChildren() }while(0); - if(l_actualSize != l_expectedSize) - { - /*@ - * @errortype ERRORLOG::ERRL_SEV_UNRECOVERABLE - * @moduleid fapi2::MOD_FAPI2_PLAT_GET_CHILDREN_TEST - * @reasoncode fapi2::RC_INVALID_CHILD_COUNT - * @userdata1[0:31] Expected Child Count - * @userdata1[32:63] Actual Child Count - * @userdata2 Parent HUID - * @devdesc Invalid amount of child cores found - * on a proc - */ - l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, - fapi2::MOD_FAPI2_PLAT_GET_CHILDREN_TEST, - fapi2::RC_INVALID_CHILD_COUNT, - TWO_UINT32_TO_UINT64( - TO_UINT32( - l_expectedSize), - TO_UINT32( - l_actualSize)), - l_targetHuid, - true/*SW Error*/); - errlCommit(l_err,HWPF_COMP_ID); - TS_FAIL("test_fapi2GetChildren Fail, for HUID: %d , expected %d children , found %d ", l_targetHuid,l_expectedSize,l_actualSize ); - } FAPI_INF("fapi2GetChildrenTest:: Test Complete. %d/%d fails", numFails , numTests); } @@ -818,7 +799,6 @@ void test_fapi2GetChildrenFilter() uint32_t l_targetHuid = 0xFFFFFFFF; uint32_t l_actualSize = 0; uint32_t l_expectedSize = 0; - errlHndl_t l_err = nullptr; TARGETING::Target * l_proc = nullptr; TARGETING::TargetHandleList l_chipList; do @@ -835,7 +815,7 @@ void test_fapi2GetChildrenFilter() } else { - TS_FAIL("test_fapi2GetChildren Fail: could not find any proc, skipping tests"); + TS_FAIL("test_fapi2GetChildrenFilter Fail: could not find any proc, skipping tests"); numFails++; break; } @@ -876,7 +856,7 @@ void test_fapi2GetChildrenFilter() if(l_actualSize != l_expectedSize) { numFails++; - break; + TS_FAIL("test_fapi2GetChildrenFilter Fail on PERV/ALL_CORES, for HUID: 0x%.8X , expected %d children , found %d ", l_targetHuid,l_expectedSize,l_actualSize ); } // PERV - TARGET_FILTER_CORE1 @@ -890,7 +870,7 @@ void test_fapi2GetChildrenFilter() if(l_actualSize != l_expectedSize) { numFails++; - break; + TS_FAIL("test_fapi2GetChildrenFilter Fail on PERV/CORE1, for HUID: 0x%.8X , expected %d children , found %d ", l_targetHuid,l_expectedSize,l_actualSize ); } if (isHwValid(l_proc, MY_MC)) @@ -906,13 +886,26 @@ void test_fapi2GetChildrenFilter() if(l_actualSize != l_expectedSize) { numFails++; - break; + TS_FAIL("test_fapi2GetChildrenFilter Fail on PERV/ALL_MC, for HUID: 0x%.8X , expected %d children , found %d ", l_targetHuid,l_expectedSize,l_actualSize ); } } // PERV - SYNC_MODE_ALL_IO_EXCEPT_NEST - // NOTE: 2 of 4 OBUS are Cumulus only, so expect 8 instead of 10 returned - l_expectedSize = 8; + l_expectedSize = 0; + TARGETING::ATTR_MODEL_type l_model = l_proc->getAttr<TARGETING::ATTR_MODEL>(); + if (l_model == TARGETING::MODEL_NIMBUS) + { + // NOTE: 2 of 4 OBUS are Cumulus only, so expect 8 instead of 10 returned + l_expectedSize = 8; + } + else if (l_model == TARGETING::MODEL_CUMULUS) + { + l_expectedSize = 10; + } + else if (l_model == TARGETING::MODEL_AXONE) + { + l_expectedSize = 10; + } l_childPERVs = fapi2_procTarget.getChildren<fapi2::TARGET_TYPE_PERV>( TARGET_FILTER_SYNC_MODE_ALL_IO_EXCEPT_NEST, TARGET_STATE_PRESENT); @@ -922,37 +915,11 @@ void test_fapi2GetChildrenFilter() if(l_actualSize != l_expectedSize) { numFails++; - break; + TS_FAIL("test_fapi2GetChildrenFilter Fail on PERV/ALL_IO_EXCEPT_NEST, for HUID: 0x%.8X , expected %d children , found %d ", l_targetHuid,l_expectedSize,l_actualSize ); } }while(0); - if(l_actualSize != l_expectedSize) - { - /*@ - * @errortype ERRORLOG::ERRL_SEV_UNRECOVERABLE - * @moduleid fapi2::MOD_FAPI2_PLAT_GET_CHILDREN_FILTER_TEST - * @reasoncode fapi2::RC_INVALID_CHILD_COUNT - * @userdata1[0:31] Expected Child Count - * @userdata1[32:63] Actual Child Count - * @userdata2 Parent HUID - * @devdesc Invalid amount of child cores found - * on a proc - */ - l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, - fapi2::MOD_FAPI2_PLAT_GET_CHILDREN_FILTER_TEST, - fapi2::RC_INVALID_CHILD_COUNT, - TWO_UINT32_TO_UINT64( - TO_UINT32( - l_expectedSize), - TO_UINT32( - l_actualSize)), - l_targetHuid, - true/*SW Error*/); - errlCommit(l_err,HWPF_COMP_ID); - TS_FAIL("test_fapi2GetChildrenFilter Fail, for HUID: 0x%X , expected %d children , found %d ", l_targetHuid,l_expectedSize,l_actualSize ); - } - FAPI_INF("test_fapi2GetChildrenFilter: Test Complete. %d/%d fails", numFails , numTests); } @@ -966,10 +933,12 @@ void test_fapi2getChildTargetsForCDG() int numFails = 0; TARGETING::Target * l_proc = nullptr; size_t l_expectedDimms = 0; + TARGETING::TargetHandleList l_chipList; +// These port and socket arguments are not valid for Axone targets +#ifndef CONFIG_AXONE size_t l_expectedDimmsUnderPort0 = 0; size_t l_expectedDimmsUnderPort1 = 0; - TARGETING::TargetHandleList l_chipList; - +#endif do { FAPI_DBG("start of test_fapi2getChildTargetsForCDG()"); @@ -992,20 +961,24 @@ void test_fapi2getChildTargetsForCDG() if (l_proc->getAttr<TARGETING::ATTR_MODEL>() == TARGETING::MODEL_NIMBUS) { l_expectedDimms = 16; +// These port and socket arguments are not valid for Axone targets +#ifndef CONFIG_AXONE l_expectedDimmsUnderPort0 = l_expectedDimms; l_expectedDimmsUnderPort1 = 0; +#endif } else if (l_proc->getAttr<TARGETING::ATTR_MODEL>() == TARGETING::MODEL_CUMULUS) { l_expectedDimms = 8; +// These port and socket arguments are not valid for Axone targets +#ifndef CONFIG_AXONE l_expectedDimmsUnderPort0 = l_expectedDimms/2; l_expectedDimmsUnderPort1 = l_expectedDimms/2; +#endif } else if (l_proc->getAttr<TARGETING::ATTR_MODEL>() == TARGETING::MODEL_AXONE) { l_expectedDimms = 9; - l_expectedDimmsUnderPort0 = 0xFF; //wrong - l_expectedDimmsUnderPort1 = 0xFF; //wrong } else //both are nullptr { @@ -1035,6 +1008,9 @@ void test_fapi2getChildTargetsForCDG() numFails++; } +// These port and socket arguments are not valid for Axone targets +// so skip testing them +#ifndef CONFIG_AXONE // All dimms under port 0 fapi2::getChildTargetsForCDG(fapi2_procTarget, fapi2::TARGET_TYPE_DIMM, @@ -1047,11 +1023,9 @@ void test_fapi2getChildTargetsForCDG() if(l_dimmList.size() != l_expectedDimmsUnderPort0) { -#ifndef CONFIG_AXONE_BRING_UP TS_FAIL("test_fapi2getChildTargetsForCDG: Dimm count %d under port 0 not equal expected %d", l_dimmList.size(),l_expectedDimmsUnderPort0); numFails++; -#endif } // All dimms under port 1 @@ -1066,11 +1040,9 @@ void test_fapi2getChildTargetsForCDG() if(l_dimmList.size() != l_expectedDimmsUnderPort1) { -#ifndef CONFIG_AXONE_BRING_UP TS_FAIL("test_fapi2getChildTargetsForCDG: Dimm count %d under port 1 not equal expected %d", l_dimmList.size(),l_expectedDimmsUnderPort1); numFails++; -#endif } // All dimms under socket 0 @@ -1084,11 +1056,9 @@ void test_fapi2getChildTargetsForCDG() numTests++; if(l_dimmList.size() != l_expectedDimms) { -#ifndef CONFIG_AXONE_BRING_UP - TS_FAIL("test_fapi2getChildTargetsForCDG: Dimm count %d under socket 0 not equal expected %d", + TS_FAIL("test_fapi2getChildTargetsForCDG: Dimm count %d under socket 0x0, all ports, not equal expected %d", l_dimmList.size(),l_expectedDimms); numFails++; -#endif } // All dimms under socket 1 @@ -1106,6 +1076,7 @@ void test_fapi2getChildTargetsForCDG() l_dimmList.size(),0); numFails++; } +#endif }while(0); diff --git a/src/usr/fapi2/test/fapi2GetVpdTest.H b/src/usr/fapi2/test/fapi2GetVpdTest.H index 8a8dc0849..8f86430a0 100644 --- a/src/usr/fapi2/test/fapi2GetVpdTest.H +++ b/src/usr/fapi2/test/fapi2GetVpdTest.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2016,2017 */ +/* Contributors Listed Below - COPYRIGHT 2016,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -46,7 +46,7 @@ public: void testGetVPD(void) { -#ifdef CONFIG_SECUREBOOT +#if (defined CONFIG_SECUREBOOT && ! defined CONFIG_AXONE) errlHndl_t pError=NULL; do { @@ -71,7 +71,7 @@ void testGetVPD(void) testGetVPD_DQ(); testGetVPD_CK(); -#ifdef CONFIG_SECUREBOOT +#if (defined CONFIG_SECUREBOOT && ! defined CONFIG_AXONE) pError = PNOR::unloadSecureSection(PNOR::MEMD); if(pError) { diff --git a/src/usr/fapi2/test/fapi2MmioAccessTest.H b/src/usr/fapi2/test/fapi2MmioAccessTest.H index 3ba0f31c0..fffec22e8 100644 --- a/src/usr/fapi2/test/fapi2MmioAccessTest.H +++ b/src/usr/fapi2/test/fapi2MmioAccessTest.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2018 */ +/* Contributors Listed Below - COPYRIGHT 2018,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -38,7 +38,7 @@ #include <fapi2TestUtils.H> #include <p9_mmiotests.H> #include <plat_hwp_invoker.H> -#include <config.h> +#include <test/exptest_utils.H> using namespace fapi2; @@ -110,10 +110,22 @@ void test_fapi2MmioInvalidSizes() // Get a list of all of the OCMB chips TARGETING::getAllChips(l_ocmbTargetList, TARGETING::TYPE_OCMB_CHIP, true); + if (!iv_serializeTestMutex) + { + TS_FAIL("test_fapi2MmioInvalidSizes(): unable to get test mutex"); + return; + } + mutex_lock(iv_serializeTestMutex); + for (auto & l_ocmb: l_ocmbTargetList) { Target<fapi2::TARGET_TYPE_OCMB_CHIP> fapi2_ocmbTarget( l_ocmb ); - + auto first_ocmb_info = l_ocmb->getAttr<TARGETING::ATTR_SCOM_SWITCHES>(); + if (!first_ocmb_info.useInbandScom) + { + TS_FAIL("test_fapi2MmioInvalidSizes() - scom access is not using inband"); + continue; + } numTests++; FAPI_INVOKE_HWP(l_errl, p9_mmiotest_indivisible_by_section_size, fapi2_ocmbTarget); if(l_errl != nullptr) @@ -126,6 +138,12 @@ void test_fapi2MmioInvalidSizes() TS_FAIL("No error from p9_mmiotest_indivisible_by_section_size !!"); numFails++; } + auto second_ocmb_info = l_ocmb->getAttr<TARGETING::ATTR_SCOM_SWITCHES>(); + if (!second_ocmb_info.useInbandScom) + { + TS_FAIL("p9_mmiotest_indivisible_by_section_size turned off mmio operations"); + l_ocmb->setAttr<TARGETING::ATTR_SCOM_SWITCHES>(first_ocmb_info); + } numTests++; FAPI_INVOKE_HWP(l_errl, p9_mmiotest_invalid_section_size, fapi2_ocmbTarget); @@ -139,7 +157,14 @@ void test_fapi2MmioInvalidSizes() TS_FAIL("No error from p9_mmiotest_invalid_section_size !!"); numFails++; } + auto third_ocmb_info = l_ocmb->getAttr<TARGETING::ATTR_SCOM_SWITCHES>(); + if (!third_ocmb_info.useInbandScom) + { + TS_FAIL("p9_mmiotest_invalid_section_size turned off mmio operations"); + l_ocmb->setAttr<TARGETING::ATTR_SCOM_SWITCHES>(first_ocmb_info); + } } + mutex_unlock(iv_serializeTestMutex); FAPI_INF("test_fapi2MmioInvalidSizes Test Complete. %d/%d fails", numFails, numTests); } @@ -152,7 +177,6 @@ void test_fapi2MmioAccess() int numTests = 0; int numFails = 0; -#ifndef CONFIG_AXONE_BRING_UP errlHndl_t l_errl = nullptr; // Create a vector of TARGETING::Target pointers @@ -161,6 +185,12 @@ void test_fapi2MmioAccess() // Get a list of all of the OCMB chips TARGETING::getAllChips(l_chipList, TARGETING::TYPE_OCMB_CHIP, true); + if (!iv_serializeTestMutex) + { + TS_FAIL("test_fapi2MmioAccess(): unable to get test mutex"); + return; + } + mutex_lock(iv_serializeTestMutex); for (auto & l_ocmb: l_chipList) { Target<fapi2::TARGET_TYPE_OCMB_CHIP> l_fapi2_target( l_ocmb ); @@ -213,11 +243,41 @@ void test_fapi2MmioAccess() l_errl = nullptr; } } -#endif + mutex_unlock(iv_serializeTestMutex); FAPI_INF("fapi2MmioAccessTest Test Complete. %d/%d fails", numFails, numTests); } +/** + * @brief Constructor + */ +Fapi2MmioAccessTest() : CxxTest::TestSuite() +{ + // All modules are loaded by runtime, + // so testcase loading of modules is not required +#ifndef __HOSTBOOT_RUNTIME + errlHndl_t err = nullptr; + err = exptest::loadModule(exptest::MSS_LIBRARY_NAME); + if(err) + { + TS_FAIL("Fapi2MmioAccessTest() - Constuctor: failed to load MSS module"); + errlCommit( err, TARG_COMP_ID ); + } +#endif + iv_serializeTestMutex = exptest::getTestMutex(); +}; + +/** + * @brief Deconstructor + */ +~Fapi2MmioAccessTest() +{ +} + + +private: + // This is used for tests that need to not run operations at the same time + TARGETING::HB_MUTEX_SERIALIZE_TEST_LOCK_ATTR iv_serializeTestMutex; }; diff --git a/src/usr/fapi2/test/fapi2MvpdTestCxx.H b/src/usr/fapi2/test/fapi2MvpdTestCxx.H index 224879070..92d791908 100644 --- a/src/usr/fapi2/test/fapi2MvpdTestCxx.H +++ b/src/usr/fapi2/test/fapi2MvpdTestCxx.H @@ -326,7 +326,8 @@ public: #ifdef CONFIG_EARLY_TESTCASES // Requires some prereqs of step7 - FAPI_INF("Skipping poundv tests"); + FAPI_INF("Skipping poundv tests due to CONFIG_EARLY_TESTCASES"); + #else fapi2::ReturnCode l_rc; @@ -421,7 +422,8 @@ public: #ifdef CONFIG_EARLY_TESTCASES // Requires some prereqs of step7 - FAPI_INF("Skipping poundv tests"); + FAPI_INF("Skipping poundw tests due to CONFIG_EARLY_TESTCASES"); + #else fapi2::ReturnCode l_rc; diff --git a/src/usr/fapi2/test/fapi2SpdTestCxx.H b/src/usr/fapi2/test/fapi2SpdTestCxx.H index 2ccd457dc..d033401e8 100644 --- a/src/usr/fapi2/test/fapi2SpdTestCxx.H +++ b/src/usr/fapi2/test/fapi2SpdTestCxx.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2016 */ +/* Contributors Listed Below - COPYRIGHT 2016,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -37,6 +37,7 @@ #include <errl/errlentry.H> #include <devicefw/driverif.H> #include <fapi2_spd_access.H> +#include <vpd/spdenums.H> using namespace TARGETING; @@ -52,76 +53,127 @@ class SPDTest: public CxxTest::TestSuite { public: - /** - * @brief Test SPD get Interface DIMMs. - */ - void testGetSPD ( void ) - { - fapi2::ReturnCode l_rc; - size_t l_size = 0; - uint8_t * l_blobData = NULL; - - FAPI_INF( "testGetSPD - Enter" ); - - do - { - TARGETING::Target * i_pTarget = NULL; - - // Get DIMM Targets - TargetHandleList dimmList; - getDIMMTargets( dimmList ); - - // Should get atleast one - if( ( 0 == dimmList.size() ) || - ( NULL == dimmList[0] ) ) - { - FAPI_INF( "testGetSPD- No DIMMs found!"); - break; - } - - // Work on the first DIMM target - i_pTarget = dimmList[0]; - - // convert to fapi2 target - fapi2::Target<fapi2::TARGET_TYPE_DIMM> fapi2_Target(i_pTarget); - - // SPD interface call with NULL blob to get size data - l_rc = fapi2::getSPD(fapi2_Target, NULL, l_size); - - // Expect to return the size or non failure - if( !l_size || (l_rc != fapi2::FAPI2_RC_SUCCESS) ) - { - TS_FAIL("testGetSPD: Failed getting the size of the mem buffer"); - break; - } - - // allocate the blob data of mem size length to hold data - l_blobData = reinterpret_cast<uint8_t *>(malloc(l_size)); - memset(l_blobData,0,l_size); - - l_rc = fapi2::getSPD(fapi2_Target,l_blobData, l_size); - if ( l_rc != fapi2::FAPI2_RC_SUCCESS ) - { - TS_FAIL( "testGetSPD- Failed to read data from DIMM with HUID= 0x%x", - TARGETING::get_huid(i_pTarget)); - break; - } - - FAPI_DBG("getSPD: SPD data for DIMM with HUID=0x%.8X Size %d Blob %d", - TARGETING::get_huid(i_pTarget), - l_size, - l_blobData); - - } while(0); - - if( NULL != l_blobData ) - { - free( l_blobData ); - l_blobData = NULL; - } - - FAPI_INF( "testGetSPD - Exit" ); - } + /** + * @brief Test SPD get Interface DIMMs. + */ + void testGetSPD ( void ) + { + fapi2::ReturnCode l_rc; + size_t l_spdSize = 0; + uint8_t * l_blobData = NULL; + + FAPI_INF( "testGetSPD - Enter" ); + + // Get DIMM Targets + TargetHandleList dimmList; + getDIMMTargets( dimmList ); + + // Should get atleast one + if( ( 0 == dimmList.size() ) || + ( NULL == dimmList[0] ) ) + { + TS_FAIL( "testGetSPD- No DIMMs found!"); + } + + for( auto l_tDimm : dimmList ) + { + + // convert to fapi2 target + fapi2::Target<fapi2::TARGET_TYPE_DIMM> l_fDimm(l_tDimm); + + // SPD interface call with NULL blob to get size data + l_rc = fapi2::getSPD(l_fDimm, NULL, l_spdSize); + + // Expect to return the size or non failure + if( !l_spdSize || (l_rc != fapi2::FAPI2_RC_SUCCESS) ) + { + TS_FAIL("testGetSPD: Failed getting the size of the mem buffer - Dimm %.8X", TARGETING::get_huid(l_tDimm)); + continue; + } + + // allocate the blob data of mem size length to hold data + l_blobData = reinterpret_cast<uint8_t *>(malloc(l_spdSize)); + memset(l_blobData,0,l_spdSize); + + l_rc = fapi2::getSPD(l_fDimm,l_blobData, l_spdSize); + if ( l_rc != fapi2::FAPI2_RC_SUCCESS ) + { + TS_FAIL( "testGetSPD- Failed to read data from DIMM with HUID= 0x%x", + TARGETING::get_huid(l_tDimm)); + continue; + } + + uint8_t l_memModule = 0x0; + size_t l_memSize = sizeof(uint8_t); + + auto l_errl = deviceRead(l_tDimm, + (void *)&l_memModule, + l_memSize, + DEVICE_SPD_ADDRESS(SPD::MODULE_TYPE)); + + if ( l_errl ) + { + TS_FAIL( "testGetSPD- Failed to deviceRead with HUID= 0x%x", + TARGETING::get_huid(l_tDimm)); + continue; + } + + uint8_t l_memGen = 0x0; + l_errl = deviceRead(l_tDimm, + (void *)&l_memGen, + l_memSize, + DEVICE_SPD_ADDRESS(SPD::BASIC_MEMORY_TYPE)); + + if ( l_errl ) + { + TS_FAIL( "testGetSPD- Failed to deviceRead with HUID= 0x%x", + TARGETING::get_huid(l_tDimm)); + continue; + } + + // figure out the expected size based on the memory type + size_t l_compareSize = 0; + if( (l_memModule == SPD::MEM_DDIMM) && (l_memGen == SPD::MEM_DDR4) ) + { + l_compareSize = SPD::OCMB_SPD_EFD_COMBINED_SIZE; + } + else if( (l_memModule != SPD::MEM_DDIMM) && (l_memGen == SPD::MEM_DDR4) ) + { + l_compareSize = SPD::DDR4_SPD_SIZE; + } + else if( l_memGen == SPD::MEM_DDR3 ) + { + l_compareSize = SPD::DDR3_SPD_SIZE; + } + else + { + TS_FAIL( "testGetSPD - Unknown memory type for %.8X : module=0x%X, gen=0x%X", + TARGETING::get_huid(l_tDimm), l_memModule, l_memGen ); + continue; + } + + if( l_compareSize != l_spdSize ) + { + TS_FAIL( "testGetSPD - Wrong SPD size for %.8X : module=0x%X, gen=0x%X, exp=%d, act=%d", + TARGETING::get_huid(l_tDimm), l_memModule, l_memGen, + l_compareSize, l_spdSize); + continue; + } + + FAPI_DBG("getSPD: SPD data for DIMM with HUID=0x%.8X Size %d Blob %d", + TARGETING::get_huid(l_tDimm), + l_spdSize, + l_blobData); + } + + if( NULL != l_blobData ) + { + free( l_blobData ); + l_blobData = NULL; + } + + FAPI_INF( "testGetSPD - Exit" ); + } }; diff --git a/src/usr/fapi2/test/fapi2Test.mk b/src/usr/fapi2/test/fapi2Test.mk index f7dc4d002..074e4e45d 100644 --- a/src/usr/fapi2/test/fapi2Test.mk +++ b/src/usr/fapi2/test/fapi2Test.mk @@ -72,6 +72,8 @@ else ## All hostboot IPL time tests TESTS += ${shell ls ${ROOTPATH}/src/usr/fapi2/test/*Test.H | \ sort | xargs} +EXTRAINCDIR += ${ROOTPATH}/src/usr/expaccess/ + OBJS += p9_i2ctests.o OBJS += p9_mmiotests.o diff --git a/src/usr/fapi2/test/fapi2TestUtils.H b/src/usr/fapi2/test/fapi2TestUtils.H index 7b724a094..011538c63 100644 --- a/src/usr/fapi2/test/fapi2TestUtils.H +++ b/src/usr/fapi2/test/fapi2TestUtils.H @@ -225,7 +225,10 @@ enum PERVASIVE_CHILDREN { PERV_OBUS_CHILDREN = 1, PERV_CAPP_NIMBUS_CHILDREN = 1, PERV_CAPP_CUMULUS_CHILDREN = 2, + PERV_CAPP_AXONE_CHILDREN = 1, PERV_OBUS_BRICK_CHILDREN = 3, + PERV_OBUS_BRICK03_AXONE_CHILDREN = 2, + PERV_OBUS_BRICK12_AXONE_CHILDREN = 1, PERV_MCBIST_CHILDREN = 1, PERV_MCS_CHILDREN = 2, PERV_MCA_CHILDREN = 4, diff --git a/src/usr/fapi2/test/p9_mmiotests.C b/src/usr/fapi2/test/p9_mmiotests.C index 264e88117..1214e20fb 100644 --- a/src/usr/fapi2/test/p9_mmiotests.C +++ b/src/usr/fapi2/test/p9_mmiotests.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2018 */ +/* Contributors Listed Below - COPYRIGHT 2018,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -37,6 +37,13 @@ #include <sbe/sbe_common.H> +// Write/Read from the inband response address (shouldn't hurt anything) +// Constants from #include <lib/inband/exp_inband.H> +static const uint64_t EXPLR_IB_MMIO_OFFSET = 0x0000000100000000ull; // 4GB +static const uint64_t EXPLR_IB_SRAM_BASE = 0x01000000; // MSCCRNGE 01000000 020FFFFF +static const uint64_t EXPLR_IB_RSP_SRAM_ADDR = EXPLR_IB_SRAM_BASE | 0x03FF00; +static const uint64_t EXPLR_IB_RSP_ADDR = EXPLR_IB_MMIO_OFFSET | EXPLR_IB_RSP_SRAM_ADDR; + fapi2::ReturnCode p9_mmiotest_getmmio_invalid_target( fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target) { @@ -48,7 +55,7 @@ fapi2::ReturnCode p9_mmiotest_getmmio_invalid_target( FAPI_INF("Do getMMIO on a proc target for 8 bytes"); FAPI_TRY(fapi2::getMMIO(i_target, - 0x1000, // mmio address relative to target + EXPLR_IB_RSP_ADDR, // mmio address relative to target 8, // mmio transaction size l_mmiodata)); fapi_try_exit: @@ -75,7 +82,7 @@ fapi2::ReturnCode p9_mmiotest_putmmio_invalid_target( FAPI_INF( "Do putMMIO on proc target" ); FAPI_TRY(fapi2::putMMIO(i_target, - 0x1000, + EXPLR_IB_RSP_ADDR, 4, l_mmiodata)); @@ -100,7 +107,7 @@ fapi2::ReturnCode p9_mmiotest_indivisible_by_section_size( FAPI_INF("Do getMMIO on a target for 10 bytes"); FAPI_TRY(fapi2::getMMIO(i_target, - 0x1000, // mmio address relative to target + EXPLR_IB_RSP_ADDR, // mmio address relative to target 8, // mmio transaction size l_mmiodata)); fapi_try_exit: @@ -123,7 +130,7 @@ fapi2::ReturnCode p9_mmiotest_invalid_section_size( FAPI_INF("Do getMMIO on a target for 12 bytes"); FAPI_TRY(fapi2::getMMIO(i_target, - 0x1000, // mmio address relative to target + EXPLR_IB_RSP_ADDR, // mmio address relative to target 12, // mmio transaction size l_mmiodata)); fapi_try_exit: @@ -149,7 +156,7 @@ fapi2::ReturnCode p9_mmiotest_getmmio_pass( FAPI_INF("Do single-read transaction getMMIO on an OCMB target"); FAPI_TRY(fapi2::getMMIO(i_target, - 0x1000, + EXPLR_IB_RSP_ADDR, l_mmiodataSize, l_mmiodata) ); @@ -157,7 +164,7 @@ fapi2::ReturnCode p9_mmiotest_getmmio_pass( l_mmiodata.resize(l_mmiodataSize*2); // do a double mmio transaction FAPI_INF("Do double-read transaction getMMIO on an OCMB target"); FAPI_TRY(fapi2::getMMIO(i_target, - 0x1000, + EXPLR_IB_RSP_ADDR, l_mmiodataSize, l_mmiodata) ); @@ -183,7 +190,7 @@ fapi2::ReturnCode p9_mmiotest_double_read_pass( FAPI_INF("Do first getMMIO on an ocmb target"); FAPI_TRY(fapi2::getMMIO(i_target, - 0x1000, + EXPLR_IB_RSP_ADDR, l_mmioTransactionSize, l_1st_read) ); @@ -195,7 +202,7 @@ fapi2::ReturnCode p9_mmiotest_double_read_pass( FAPI_INF("Do second getMMIO on an ocmb target"); FAPI_TRY(fapi2::getMMIO(i_target, - 0x1000, + EXPLR_IB_RSP_ADDR, l_mmioTransactionSize, l_2nd_read) ); @@ -237,7 +244,7 @@ fapi2::ReturnCode p9_mmiotest_putmmio_pass( FAPI_INF("Do putMMIO on OCMB target"); FAPI_TRY(fapi2::putMMIO(i_target, - 0x1000, + EXPLR_IB_RSP_ADDR, 4, l_mmiodata)); fapi_try_exit: @@ -266,14 +273,14 @@ fapi2::ReturnCode p9_mmiotest_write_read_pass( // Write out a known value (name of this test) FAPI_INF("Calling putMMIO on the target (size: %d)", l_data_size); - FAPI_TRY(fapi2::putMMIO(i_target, 0x1000, + FAPI_TRY(fapi2::putMMIO(i_target, EXPLR_IB_RSP_ADDR, l_mmioTransactionSize, l_mmio_data)); // now read it out and verify it was written correctly FAPI_INF("Now read the just written data"); l_read_mmio_data.resize(l_data_size); FAPI_TRY(fapi2::getMMIO(i_target, - 0x1000, + EXPLR_IB_RSP_ADDR, l_mmioTransactionSize, l_read_mmio_data)); |