diff options
Diffstat (limited to 'src/usr/fapi2/attribute_service.C')
-rw-r--r-- | src/usr/fapi2/attribute_service.C | 441 |
1 files changed, 432 insertions, 9 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 |