| From 8afc07837b303e5621ba28fed8a070eba633475d Mon Sep 17 00:00:00 2001 |
| From: aalugore <aalugore@us.ibm.com> |
| Date: Mon, 24 Aug 2015 13:42:24 -0500 |
| Subject: [PATCH] Function to set Nest Frequency based off DIMM memory |
| capability |
| |
| -Needed for 32x32GB DIMM support |
| -Finds max capable frequency of system and all present DIMMs |
| and deconfigures any DIMM that cannot run at desired frequency |
| -If necessary, Sets Nest Freq and triggers SBE update |
| |
| Change-Id: I9bba92f55f1b67ff4a15d79113f19d39272ec72d |
| RTC:122884 |
| Depends-on:I1dca7196cd02a2704a238665b73b522c9e103936 |
| --- |
| src/include/usr/hwpf/hwpf_reasoncodes.H | 4 +- |
| src/include/usr/isteps/istep12list.H | 4 +- |
| src/include/usr/sbe/sbeif.H | 16 + |
| src/include/usr/targeting/common/target.H | 11 + |
| src/include/util/algorithm.H | 18 +- |
| src/include/util/align.H | 17 +- |
| src/usr/hwpf/hwp/mc_config/mc_config.C | 437 ++++++++++++++++++++- |
| src/usr/hwpf/hwp/memory_attributes.xml | 12 +- |
| src/usr/hwpf/plat/fapiPlatUtil.C | 2 +- |
| src/usr/sbe/sbe_update.C | 62 +++ |
| src/usr/targeting/common/target.C | 47 +++ |
| .../targeting/common/xmltohb/attribute_types.xml | 10 +- |
| 12 files changed, 608 insertions(+), 32 deletions(-) |
| |
| diff --git a/src/include/usr/hwpf/hwpf_reasoncodes.H b/src/include/usr/hwpf/hwpf_reasoncodes.H |
| index e1a00da..ea326c1 100644 |
| --- a/src/include/usr/hwpf/hwpf_reasoncodes.H |
| +++ b/src/include/usr/hwpf/hwpf_reasoncodes.H |
| @@ -80,7 +80,9 @@ namespace fapi |
| MOD_PLAT_MVPD_GET_VLTG_BUCKET_ATTR = 0x26, |
| MOD_PLAT_ATTR_SVC_CEN_DQ_TO_DIMM_CONN_DQ = 0x27, |
| MOD_PLAT_ATTR_SVC_GET_MEM_ATTR_DATA = 0x28, |
| - |
| + MOD_GET_WOF_FREQ_UPLIFT_SELECTED = 0x29, |
| + MOD_SET_NEST_FREQ = 0x2A, |
| + MOD_FIND_MAX_DMI_SPD = 0x2B, |
| }; |
| |
| /** |
| diff --git a/src/include/usr/isteps/istep12list.H b/src/include/usr/isteps/istep12list.H |
| index 2e724f2..f668733 100644 |
| --- a/src/include/usr/isteps/istep12list.H |
| +++ b/src/include/usr/isteps/istep12list.H |
| @@ -5,7 +5,7 @@ |
| /* */ |
| /* OpenPOWER HostBoot Project */ |
| /* */ |
| -/* Contributors Listed Below - COPYRIGHT 2012,2014 */ |
| +/* Contributors Listed Below - COPYRIGHT 2012,2015 */ |
| /* [+] Google Inc. */ |
| /* [+] International Business Machines Corp. */ |
| /* */ |
| @@ -105,6 +105,8 @@ const DepModInfo g_istep12Dependancies = { |
| #ifndef CONFIG_VPO_COMPILE |
| DEP_LIB(libmc_config.so), |
| #endif |
| + DEP_LIB(libsbe.so), |
| + DEP_LIB(libbuild_winkle_images.so), |
| NULL |
| } |
| }; |
| diff --git a/src/include/usr/sbe/sbeif.H b/src/include/usr/sbe/sbeif.H |
| index b00e01f..ff397ca 100644 |
| --- a/src/include/usr/sbe/sbeif.H |
| +++ b/src/include/usr/sbe/sbeif.H |
| @@ -94,6 +94,22 @@ namespace SBE |
| */ |
| errlHndl_t resolveProcessorSbeSeeproms(); |
| |
| + /** |
| + * @brief Determines whether we are on the Golden side or not |
| + * |
| + * @param[out] o_isGolden boolean, True if we are on Golden side, False |
| + * otherwise. |
| + * |
| + * @return errlHndl_t Error log handle on failure. |
| + * |
| + * NOTE: -Golden Side means we booted from the Golden Seeprom pointing |
| + * at the Golden side of PNOR. |
| + * -Using master processor to make this determination. |
| + */ |
| + |
| + errlHndl_t isGoldenSide( bool & o_isGolden ); |
| + |
| + |
| |
| } //end namespace SBE |
| |
| diff --git a/src/include/usr/targeting/common/target.H b/src/include/usr/targeting/common/target.H |
| index 25e7be6..bf5b7da 100644 |
| --- a/src/include/usr/targeting/common/target.H |
| +++ b/src/include/usr/targeting/common/target.H |
| @@ -672,6 +672,17 @@ const char* Target::getAttrAsString() const |
| return attrToString<A>(l_attrValue); |
| } |
| |
| +// Function to set various frequency related attributes |
| +/** |
| + * @brief - sets various attributes directly related to the nest frequency. |
| + * |
| + * @param[in] i_sys - top level system target to set attributes for |
| + * @param[in] i_newNestFreq - the new nest frequency to base all the attributes |
| + * off of. |
| + */ |
| +void setFrequencyAttributes(Target * i_sys, uint32_t i_newNestFreq); |
| + |
| + |
| // WARNING: The following #include imports any platform specific template |
| // specializations for getAttr and tryGetAttr |
| #include <targeting/adapters/targetadapter.H> |
| diff --git a/src/include/util/algorithm.H b/src/include/util/algorithm.H |
| index 54baa02..dac0f47 100644 |
| --- a/src/include/util/algorithm.H |
| +++ b/src/include/util/algorithm.H |
| @@ -5,7 +5,9 @@ |
| /* */ |
| /* OpenPOWER HostBoot Project */ |
| /* */ |
| -/* COPYRIGHT International Business Machines Corp. 2012,2014 */ |
| +/* Contributors Listed Below - COPYRIGHT 2012,2015 */ |
| +/* [+] International Business Machines Corp. */ |
| +/* */ |
| /* */ |
| /* Licensed under the Apache License, Version 2.0 (the "License"); */ |
| /* you may not use this file except in compliance with the License. */ |
| @@ -52,6 +54,20 @@ namespace Util |
| static const T value = (a > b) ? a : b; |
| }; |
| |
| + /** |
| + * @brief - utility function that determines if a given number is |
| + * power of 2. |
| + * |
| + * @param[in] i_num - given number. |
| + * |
| + * @return bool - True if the number is a power of 2, False otherwise. |
| + */ |
| + template <typename T> |
| + bool isPow2(T i_num) |
| + { |
| + return (!(i_num & (i_num-1))); |
| + } |
| + |
| }; |
| }; |
| #endif |
| diff --git a/src/include/util/align.H b/src/include/util/align.H |
| index e0132b2..10a8369 100644 |
| --- a/src/include/util/align.H |
| +++ b/src/include/util/align.H |
| @@ -51,18 +51,7 @@ |
| #define ALIGN_MEGABYTE(u) (ALIGN_X(u,MEGABYTE)) |
| #define ALIGN_MEGABYTE_DOWN(u) (ALIGN_DOWN_X(u,MEGABYTE)) |
| |
| -// Returns a number that is aligned to the next highest power of 2 number of |
| -// pages for the given buffer. |
| -#define ALIGN_TO_NEXT_POWER_OF_TWO_PAGES(b) ({\ |
| - unsigned int v = ALIGN_PAGE(b)/PAGE_SIZE;\ |
| - v--;\ |
| - v |= v >> 1;\ |
| - v |= v >> 2;\ |
| - v |= v >> 4;\ |
| - v |= v >> 8;\ |
| - v |= v >> 16;\ |
| - v++;\ |
| - v * PAGE_SIZE;\ |
| - }) |
| - |
| +// Return a number rounded to the next power of two. |
| +#define ALIGN_POW2(u) ((u&(u-1)) ? 1 << (64 - __builtin_clzl(u)) : u) |
| +#define ALIGN_POW2_DOWN(u) (u ? 1 << (63 - __builtin_clzl(u)) : 0) |
| #endif |
| diff --git a/src/usr/hwpf/hwp/mc_config/mc_config.C b/src/usr/hwpf/hwp/mc_config/mc_config.C |
| index b2bc2f1..f29ee7c 100644 |
| --- a/src/usr/hwpf/hwp/mc_config/mc_config.C |
| +++ b/src/usr/hwpf/hwp/mc_config/mc_config.C |
| @@ -44,16 +44,19 @@ |
| |
| #include <trace/interface.H> |
| #include <initservice/taskargs.H> |
| +#include <initservice/initserviceif.H> |
| #include <errl/errlentry.H> |
| |
| #include <hwpisteperror.H> |
| +#include <hwpf/hwpf_reasoncodes.H> |
| #include <errl/errludtarget.H> |
| |
| #include <initservice/isteps_trace.H> |
| - |
| +#include <sbe/sbeif.H> |
| // targeting support |
| #include <targeting/common/commontargeting.H> |
| #include <targeting/common/utilFilter.H> |
| +#include <attributetraits.H> |
| |
| // fapi support |
| #include <fapi.H> |
| @@ -79,6 +82,8 @@ |
| #include "mss_volt/mss_volt_dimm_count.H" |
| |
| #include <config.h> |
| +#include <util/align.H> |
| +#include <util/algorithm.H> |
| |
| namespace MC_CONFIG |
| { |
| @@ -129,7 +134,8 @@ void set_eff_config_attrs_helper( const EFF_CONFIG_ATTRIBUTES_BASE i_base, |
| // Get Node Target |
| TARGETING::Target* sysTgt = NULL; |
| TARGETING::targetService().getTopLevelTarget(sysTgt); |
| - assert(sysTgt != NULL,"System target was NULL."); |
| + assert(sysTgt != NULL,"set_eff_config_attrs_helper: " |
| + "System target was NULL."); |
| |
| TARGETING::TargetHandleList l_nodeList; |
| |
| @@ -467,7 +473,8 @@ errlHndl_t setMemoryVoltageDomainOffsetVoltage() |
| |
| TARGETING::Target* pSysTarget = NULL; |
| TARGETING::targetService().getTopLevelTarget(pSysTarget); |
| - assert(pSysTarget != NULL,"System target was NULL."); |
| + assert(pSysTarget != NULL,"setMemoryVoltageDomainOffsetVoltage: " |
| + "System target was NULL."); |
| |
| typename AttributeTraits< OFFSET_DISABLEMENT_ATTR >::Type |
| disableOffsetVoltage = |
| @@ -717,13 +724,16 @@ void call_mss_volt_hwp (std::vector<TARGETING::ATTR_VMEM_ID_type>& i_VmemList, |
| l_membufFapiTargets.push_back( l_membuf_fapi_target ); |
| } |
| } |
| + |
| + TRACDCOMP(ISTEPS_TRACE::g_trac_isteps_trace, |
| + "Calling mss_volt_hwp..."); |
| FAPI_INVOKE_HWP(l_err, mss_volt_hwp, l_membufFapiTargets); |
| |
| // process return code. |
| if ( l_err ) |
| { |
| TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, |
| - "ERROR 0x%.8X: mss_volt_dimm_count HWP( ) ", |
| + "ERROR 0x%.8X: mss_volt HWP( ) ", |
| l_err->reasonCode()); |
| |
| // Create IStep error log and cross reference to error that occurred |
| @@ -872,7 +882,411 @@ void* call_mss_volt( void *io_pArgs ) |
| |
| return l_StepError.getErrorHandle(); |
| } |
| +/** |
| + * @brief - this utility function takes in the frequency in |
| + * ATTR_MRW_NEST_CAPABLE_FREQUENCIES_SYS and returns the corresponding |
| + * dmi bus speed from ATTR_MSS_NEST_CAPABLE_FREQUENCIES |
| + * |
| + * @param[in] i_freq - the input frequency |
| + * @param[in/out] io_speed - the corresponding dmi bus speed |
| + */ |
| +void sysFreq_to_dmiSpeed(ATTR_MRW_NEST_CAPABLE_FREQUENCIES_SYS_type i_freq, |
| + ATTR_MSS_NEST_CAPABLE_FREQUENCIES_type & io_speed) |
| +{ |
| + switch(i_freq) |
| + { |
| + case TARGETING::MRW_NEST_CAPABLE_FREQUENCIES_SYS_UNSUPPORTED_FREQ: |
| + TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,"Unsupported nest freq!"); |
| + io_speed = 0; |
| + break; |
| + case TARGETING::MRW_NEST_CAPABLE_FREQUENCIES_SYS_2000_MHZ: |
| + io_speed=fapi::ENUM_ATTR_MSS_NEST_CAPABLE_FREQUENCIES_8_0G; |
| + break; |
| + case TARGETING::MRW_NEST_CAPABLE_FREQUENCIES_SYS_2400_MHZ: |
| + io_speed=fapi::ENUM_ATTR_MSS_NEST_CAPABLE_FREQUENCIES_9_6G; |
| + break; |
| + case TARGETING::MRW_NEST_CAPABLE_FREQUENCIES_SYS_2000_MHZ_OR_2400_MHZ: |
| + io_speed=fapi::ENUM_ATTR_MSS_NEST_CAPABLE_FREQUENCIES_8_0G_OR_9_6G; |
| + break; |
| + default: |
| + io_speed = 0; |
| + TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,"Invalid nest freq!"); |
| + } |
| +} |
| |
| +/** |
| + * @brief - this utility function takes in the dmi bus speed enumeration |
| + * value as described in MSS_NEST_CAPABLE_FREQUENCIES and outputs |
| + * the actual corresponding nest frequency in MHz supported by the |
| + * given dmi bus speed. |
| + * |
| + * @param[in] i_speed - the input dmi bus speed |
| + * @param[in/out] io_freq - the corresponding frequency in MHz |
| + * |
| + */ |
| +void dmiSpeed_to_sysFreq(ATTR_MSS_NEST_CAPABLE_FREQUENCIES_type i_speed, |
| + ATTR_NEST_FREQ_MHZ_type & io_freq) |
| +{ |
| + switch(i_speed) |
| + { |
| + case fapi::ENUM_ATTR_MSS_NEST_CAPABLE_FREQUENCIES_8_0G: |
| + io_freq = 2000; |
| + break; |
| + case fapi::ENUM_ATTR_MSS_NEST_CAPABLE_FREQUENCIES_9_6G: |
| + io_freq = 2400; |
| + break; |
| + default: |
| + TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "Invalid dmi speed!"); |
| + io_freq = 0; |
| + } |
| +} |
| + |
| + |
| + |
| +// |
| +// calloutChildDimms |
| +// |
| +void calloutChildDimms(errlHndl_t & io_errl, const TARGETING::Target * i_membuf) |
| +{ |
| + TargetHandleList l_dimmList; |
| + |
| + // Get child dimms |
| + getChildAffinityTargets( l_dimmList, |
| + i_membuf, |
| + CLASS_NA, |
| + TYPE_DIMM ); |
| + |
| + if( !l_dimmList.empty()) |
| + { |
| + // iterate over the DIMMs and call them out |
| + TargetHandleList::iterator l_iter = l_dimmList.begin(); |
| + |
| + for(;l_iter != l_dimmList.end(); ++l_iter) |
| + { |
| + TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, |
| + "Calling out DIMM Target huid = %x", |
| + get_huid(*l_iter)); |
| + |
| + io_errl->addHwCallout( *l_iter, |
| + HWAS::SRCI_PRIORITY_MED, |
| + HWAS::DELAYED_DECONFIG, |
| + HWAS::GARD_NULL ); |
| + } |
| + } |
| + else |
| + { |
| + TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "No child DIMMs found!"); |
| + } |
| +} |
| + |
| + |
| +// TODO RTC 135720 - Support for mixed DIMM configuration with 32GB DIMMs. |
| + |
| +/** |
| + * @brief - Recursive utility function for finding the max dmi |
| + * bus speed to run at based on the nest dmi bus speed |
| + * and the membuf's dmi bus speed |
| + * |
| + * @param[in] i_iter - Iterator over the list of membufs. |
| + * @param[in] i_membufs - Pointer to the list of membufs. |
| + * @param[in/out] io_currentMaxSpeed - The speed to run at will be returned here |
| + * @param[in] i_capableNestDmiBusSpeed - The nest capable dmi bus speed. |
| + */ |
| +void findMaxSpdAndDeconfigIncompatible(TargetHandleList::iterator i_iter, |
| + TargetHandleList * i_membufs, |
| + ATTR_MSS_NEST_CAPABLE_FREQUENCIES_type & io_currentMaxSpeed, |
| + ATTR_MSS_NEST_CAPABLE_FREQUENCIES_type i_capableNestDmiBusSpeed ) |
| +{ |
| + do |
| + { |
| + // Base Case: If we are at the end of the membuf list return |
| + if(i_iter == i_membufs->end()) |
| + { |
| + // find the left most bit of the max speed found. This bit |
| + // represents the highest dmi bus speed setting we can support |
| + // across the nest and all membufs and the speed we will boot with. |
| + io_currentMaxSpeed = ALIGN_POW2_DOWN(io_currentMaxSpeed); |
| + break; |
| + } |
| + |
| + // Get the current membuf's dmi bus speed |
| + ATTR_MSS_NEST_CAPABLE_FREQUENCIES_type l_currentMembufSpd = |
| + (*i_iter)->getAttr<TARGETING::ATTR_MSS_NEST_CAPABLE_FREQUENCIES>(); |
| + |
| + // update current max speed. |
| + // Max is restricted by nest capable dmi bus speed |
| + if(((l_currentMembufSpd & i_capableNestDmiBusSpeed) != 0) && |
| + (l_currentMembufSpd > io_currentMaxSpeed)) |
| + { |
| + io_currentMaxSpeed = l_currentMembufSpd; |
| + } |
| + |
| + //Save the current membuf for when we come back from recursive call. |
| + TARGETING::Target * l_currentMembuf = (*i_iter); |
| + |
| + // Recursive call to go down the list of membufs and find the max |
| + // capable dmi speed across the nest and membufs. |
| + findMaxSpdAndDeconfigIncompatible(++i_iter, |
| + i_membufs, |
| + io_currentMaxSpeed, |
| + i_capableNestDmiBusSpeed ); |
| + |
| + // deconfigure any membufs with incompatible |
| + // speeds on the way up the stack |
| + if((l_currentMembufSpd & io_currentMaxSpeed) == 0) |
| + { |
| + TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, |
| + "Deconfiguring Membuf Huid: %X, membuf speed: %d", |
| + TARGETING::get_huid(l_currentMembuf), |
| + l_currentMembufSpd); |
| + // Membuf has incompatible frequency. Deconfigure it. |
| + /*@ |
| + * @errortype |
| + * @moduleid MOD_FIND_MAX_DMI_SPD |
| + * @reasoncode RC_INVALID_FREQ |
| + * @userdata1 HUID of membuf |
| + * @userdata2 [0:7] membuf frequency enumeration value |
| + * @userdata2 [8:15] dmi bus speed enumeration value |
| + * @devdesc Invalid nest frequency found for given membuf |
| + * @custdesc Invalid memory configuration |
| + */ |
| + errlHndl_t l_err = new ERRORLOG::ErrlEntry( |
| + ERRORLOG::ERRL_SEV_UNRECOVERABLE, |
| + fapi::MOD_FIND_MAX_DMI_SPD, |
| + fapi::RC_INVALID_FREQ, |
| + TARGETING::get_huid(l_currentMembuf), |
| + TO_UINT64(TWO_UINT8_TO_UINT16 |
| + (l_currentMembufSpd, |
| + i_capableNestDmiBusSpeed))); |
| + |
| + l_err->addHwCallout(l_currentMembuf, HWAS::SRCI_PRIORITY_HIGH, |
| + HWAS::DELAYED_DECONFIG, |
| + HWAS::GARD_NULL ); |
| + l_err->addProcedureCallout( |
| + HWAS::EPUB_PRC_MEMORY_PLUGGING_ERROR, |
| + HWAS::SRCI_PRIORITY_HIGH ); |
| + |
| + |
| + // add hw callouts for current membuf child DIMMs |
| + calloutChildDimms( l_err, l_currentMembuf ); |
| + |
| + errlCommit( l_err, HWPF_COMP_ID ); |
| + l_err = NULL; |
| + } |
| + }while( 0 ); |
| +} |
| + |
| + |
| +// |
| +// setNestBasedOffDimms |
| +// |
| +errlHndl_t setNestBasedOffDimms() |
| +{ |
| + TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, ENTER_MRK"mc_config::setNestBasedOffDimms()"); |
| + errlHndl_t l_err = NULL; |
| + bool l_isGoldenSide = false; |
| + ATTR_MRW_NEST_CAPABLE_FREQUENCIES_SYS_type l_capableNestFreq = |
| + MRW_NEST_CAPABLE_FREQUENCIES_SYS_UNSUPPORTED_FREQ; |
| + |
| + ATTR_MSS_NEST_CAPABLE_FREQUENCIES_type l_selectedBootSpeed = |
| + fapi::ENUM_ATTR_MSS_NEST_CAPABLE_FREQUENCIES_NONE; |
| + |
| + ATTR_MSS_NEST_CAPABLE_FREQUENCIES_type l_capableNestDmiBusSpeed = |
| + fapi::ENUM_ATTR_MSS_NEST_CAPABLE_FREQUENCIES_NONE; |
| + |
| + ATTR_MSS_NEST_CAPABLE_FREQUENCIES_type l_compatibleSpeed = |
| + fapi::ENUM_ATTR_MSS_NEST_CAPABLE_FREQUENCIES_NONE; |
| + |
| + ATTR_NEST_FREQ_MHZ_type l_maxFreqMhz = 0; |
| + |
| + l_isGoldenSide = false; |
| + |
| + do |
| + { |
| + // First, get the systems capable nest frequency. If 0, then stick with |
| + // already set nest frequency |
| + TARGETING::Target * l_sys = NULL; |
| + targetService().getTopLevelTarget(l_sys); |
| + |
| + uint32_t l_currentSysNestFreq = |
| + l_sys->getAttr<TARGETING::ATTR_NEST_FREQ_MHZ>(); |
| + |
| + // Check to see if we booted from the Golden side |
| + l_err = SBE::isGoldenSide(l_isGoldenSide); |
| + |
| + if(l_err) |
| + { |
| + // Error getting Golden side. Proceeding as if booting from safe Golden side |
| + TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, |
| + ERR_MRK"setNestBasedOffDimms::isGoldenSide returned an error"); |
| + errlCommit( l_err, HWPF_COMP_ID ); |
| + l_isGoldenSide = true; |
| + } |
| + |
| + if(!l_isGoldenSide) |
| + { |
| + TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, |
| + INFO_MRK"Booting from normal side. use " |
| + "MRW_NEST_CAPABLE_FREQUENCIES_SYS to calculate best freq " |
| + "across membufs"); |
| + l_capableNestFreq = l_sys->getAttr |
| + <ATTR_MRW_NEST_CAPABLE_FREQUENCIES_SYS>(); |
| + } |
| + else |
| + { |
| + // We booted using the Golden Side. Use NEST_FREQ_MHZ |
| + TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, |
| + INFO_MRK"Booting from Golden Side. Use default NEST_FREQ" |
| + "to calculate best freq across membufs"); |
| + if(l_currentSysNestFreq == 2000) |
| + { |
| + l_capableNestFreq = |
| + TARGETING::MRW_NEST_CAPABLE_FREQUENCIES_SYS_2000_MHZ; |
| + } |
| + else if( l_currentSysNestFreq == 2400 ) |
| + { |
| + l_capableNestFreq = |
| + TARGETING::MRW_NEST_CAPABLE_FREQUENCIES_SYS_2400_MHZ; |
| + } |
| + else |
| + { |
| + l_capableNestFreq = |
| + TARGETING::MRW_NEST_CAPABLE_FREQUENCIES_SYS_UNSUPPORTED_FREQ; |
| + } |
| + |
| + } |
| + |
| + // convert the frequency to its corresponding dmi bus speed |
| + sysFreq_to_dmiSpeed( l_capableNestFreq, l_capableNestDmiBusSpeed ); |
| + |
| + if(!l_capableNestDmiBusSpeed) |
| + { |
| + // Unknown frequency was given to sysFreq_to_dmiSpeed |
| + // break out of function and proceed with value already in |
| + // ATTR_NEST_FREQ_MHZ |
| + TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,"Invalid dmi speed. Proceeding with default value in NEST_FREQ_MHZ."); |
| + break; |
| + } |
| + |
| + // Get a list of all the membufs |
| + TargetHandleList l_membufs; |
| + TARGETING::getAllChips(l_membufs, TYPE_MEMBUF); |
| + TargetHandleList::iterator l_iter = l_membufs.begin(); |
| + |
| + |
| + // If the nest capable dmi bus speed can only support one setting, |
| + // that speed is the speed we want to boot with. |
| + // Deconfigure all membufs with incompatible speeds |
| + if(Util::Algorithm::isPow2(l_capableNestDmiBusSpeed)) |
| + { |
| + // We are forced to boot with the nest freq. |
| + // Save boot freq for later. |
| + l_selectedBootSpeed = l_capableNestDmiBusSpeed; |
| + |
| + |
| + ATTR_MSS_NEST_CAPABLE_FREQUENCIES_type l_membufDmiBusSpeed = 0; |
| + for(;l_iter != l_membufs.end(); ++l_iter ) |
| + { |
| + l_membufDmiBusSpeed = (*l_iter)->getAttr |
| + <TARGETING::ATTR_MSS_NEST_CAPABLE_FREQUENCIES>(); |
| + |
| + // if the intersection of the membuf's and nest's dmi speed |
| + // is zero, the membuf is incompatible with the nest and must be |
| + // deconfigured. |
| + l_compatibleSpeed = l_membufDmiBusSpeed & |
| + l_capableNestDmiBusSpeed; |
| + |
| + if(l_compatibleSpeed == |
| + fapi::ENUM_ATTR_MSS_NEST_CAPABLE_FREQUENCIES_NONE ) |
| + { |
| + TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, |
| + "Deconfiguring Membuf Huid: %X, membuf speed: %d", |
| + TARGETING::get_huid(*l_iter), |
| + l_membufDmiBusSpeed); |
| + // Membuf has incompatible frequency. Deconfigure it. |
| + /*@ |
| + * @errortype |
| + * @moduleid MOD_SET_NEST_FREQ |
| + * @reasoncode RC_INVALID_FREQ |
| + * @userdata1 HUID of membuf |
| + * @userdata2 [0:7] membuf frequency enumeration value |
| + * @userdata2 [8:15] dmi bus speed enumeration value |
| + * @devdesc Invalid nest found for given membuf |
| + * @custdesc Invalid memory configuration |
| + */ |
| + l_err = new ERRORLOG::ErrlEntry( |
| + ERRORLOG::ERRL_SEV_UNRECOVERABLE, |
| + fapi::MOD_SET_NEST_FREQ, |
| + fapi::RC_INVALID_FREQ, |
| + TARGETING::get_huid(*l_iter), |
| + TO_UINT64(TWO_UINT8_TO_UINT16 |
| + (l_membufDmiBusSpeed, |
| + l_capableNestDmiBusSpeed))); |
| + |
| + l_err->addHwCallout(*l_iter, HWAS::SRCI_PRIORITY_HIGH, |
| + HWAS::DELAYED_DECONFIG, |
| + HWAS::GARD_NULL ); |
| + |
| + |
| + // add hw callouts for current membufs child DIMMs |
| + calloutChildDimms( l_err, *l_iter); |
| + |
| + errlCommit( l_err, HWPF_COMP_ID ); |
| + l_err = NULL; |
| + continue; |
| + } |
| + |
| + } // end for-loop |
| + |
| + } |
| + else |
| + { |
| + // The nest supports multiple frequencies. Find the max dmi bus |
| + // speed shared by the nest and at least 1 membuf and boot with that |
| + // speed. |
| + findMaxSpdAndDeconfigIncompatible(l_iter, |
| + &l_membufs, |
| + l_selectedBootSpeed, |
| + l_capableNestDmiBusSpeed); |
| + |
| + } |
| + |
| + //Convert the selected boot speed to frequency |
| + dmiSpeed_to_sysFreq(l_selectedBootSpeed, l_maxFreqMhz); |
| + |
| + TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, |
| + "The max supported frequency across the processor and all dimms " |
| + "is %d", l_maxFreqMhz ); |
| + |
| + if( l_maxFreqMhz == l_currentSysNestFreq) |
| + { |
| + //do nothing. go with current Nest freq, break. |
| + TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, |
| + "Nest did not need to change. Proceeding with default NEST_FREQ"); |
| + break; |
| + } |
| + else |
| + { |
| + TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, |
| + "DIMM config determined NEST_FREQ needs to be changed to %d", |
| + l_maxFreqMhz ); |
| + //set all the attributes and trigger an sbe update |
| + TARGETING::setFrequencyAttributes(l_sys, l_maxFreqMhz); |
| + //trigger sbe update so we can update all the frequency attributes |
| + l_err = SBE::updateProcessorSbeSeeproms( |
| + SBE::SBE_UPDATE_ONLY_CHECK_NEST_FREQ); |
| + |
| + if( l_err ) |
| + { |
| + TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, |
| + "Error triggering sbe update."); |
| + } |
| + } |
| + }while( 0 ); |
| + |
| + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "setNestBasedOffDimms exit" ); |
| + return l_err; |
| +} |
| // |
| // Wrapper function to call mss_freq |
| // |
| @@ -931,6 +1345,21 @@ void* call_mss_freq( void *io_pArgs ) |
| } |
| } // End memBuf loop |
| |
| + if(! INITSERVICE::spBaseServicesEnabled() ) |
| + { |
| + //set nest frequency based off present membufs |
| + TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, |
| + INFO_MRK"Setting Nest Frequency based off Membuf capability."); |
| + l_err = setNestBasedOffDimms(); |
| + |
| + if( l_err ) |
| + { |
| + TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, |
| + ERR_MRK"Error: call_mss_freq()::setNestBasedOffDimms()"); |
| + l_StepError.addErrorDetails(l_err); |
| + } |
| + } |
| + |
| TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "call_mss_freq exit" ); |
| |
| return l_StepError.getErrorHandle(); |
| diff --git a/src/usr/hwpf/hwp/memory_attributes.xml b/src/usr/hwpf/hwp/memory_attributes.xml |
| index b4059a2..df3a2ef 100644 |
| --- a/src/usr/hwpf/hwp/memory_attributes.xml |
| +++ b/src/usr/hwpf/hwp/memory_attributes.xml |
| @@ -1,7 +1,7 @@ |
| <!-- IBM_PROLOG_BEGIN_TAG --> |
| <!-- This is an automatically generated prolog. --> |
| <!-- --> |
| -<!-- $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/centaur/working/procedures/xml/attribute_info/memory_attributes.xml,v $ --> |
| +<!-- $Source: src/usr/hwpf/hwp/memory_attributes.xml $ --> |
| <!-- --> |
| <!-- OpenPOWER HostBoot Project --> |
| <!-- --> |
| @@ -23,7 +23,7 @@ |
| <!-- --> |
| <!-- IBM_PROLOG_END_TAG --> |
| <attributes> |
| -<!-- $Id: memory_attributes.xml,v 1.159 2015/09/09 18:10:53 thi Exp $ --> |
| +<!-- $Id: memory_attributes.xml,v 1.159AL_custom 2014/11/18 17:35:29 aalugore Exp $ --> |
| <!-- DO NOT EDIT THIS FILE DIRECTLY PLEASE UPDATE THE ODS FILE AND FOLLOW THE INSTRUCTION TAB --> |
| <!-- PLEASE SEE MARK BELLOWS (BELLOWS.IBM.COM) OR OTHERS ON MEMORY TEAM FOR HELP --> |
| <!-- *********************************************************************** --> |
| @@ -108,7 +108,7 @@ Set by: PLL settings written by Dave Cadigan</description> |
| <odmChangeable/> |
| <persistRuntime/> |
| </attribute> |
| - |
| + |
| <attribute> |
| <id>ATTR_MSS_DIMM_MFG_ID_CODE</id> |
| <targetType>TARGET_TYPE_MBA_CHIPLET</targetType> |
| @@ -3051,8 +3051,8 @@ Will be set at an MBA level with one policy to be used</description> |
| <writeable/> |
| <odmVisable/> |
| <odmChangeable/> |
| - <enum>8_0G = 1, 9_6G = 2</enum> |
| -</attribute> |
| + <enum>NONE = 0, 8_0G = 1, 9_6G = 2, 8_0G_OR_9_6G = 3</enum> |
| +</attribute> |
| |
| <attribute> |
| <id>ATTR_MRW_STRICT_MBA_PLUG_RULE_CHECKING</id> |
| @@ -3425,7 +3425,7 @@ Will be set at an MBA level with one policy to be used</description> |
| <valueType>uint32</valueType> |
| <platInit/> |
| <odmVisable/> |
| -</attribute> |
| +</attribute> |
| |
| <attribute> |
| <id>ATTR_MRW_MEM_SENSOR_CACHE_ADDR_MAP</id> |
| diff --git a/src/usr/hwpf/plat/fapiPlatUtil.C b/src/usr/hwpf/plat/fapiPlatUtil.C |
| index d03b670..269c36f 100644 |
| --- a/src/usr/hwpf/plat/fapiPlatUtil.C |
| +++ b/src/usr/hwpf/plat/fapiPlatUtil.C |
| @@ -334,7 +334,7 @@ void* fapiPlatMalloc(size_t s) |
| { |
| if (s > PAGE_SIZE) |
| { |
| - s = ALIGN_TO_NEXT_POWER_OF_TWO_PAGES(s); |
| + s = PAGE_SIZE * ALIGN_POW2(ALIGN_PAGE(s) / PAGE_SIZE); |
| } |
| return malloc(s); |
| } |
| diff --git a/src/usr/sbe/sbe_update.C b/src/usr/sbe/sbe_update.C |
| index 1faad63..237838f 100644 |
| --- a/src/usr/sbe/sbe_update.C |
| +++ b/src/usr/sbe/sbe_update.C |
| @@ -3976,6 +3976,68 @@ namespace SBE |
| |
| } |
| |
| +///////////////////////////////////////////////////////////////////// |
| + errlHndl_t isGoldenSide( bool & o_isGolden ) |
| + { |
| + errlHndl_t l_errl = NULL; |
| + o_isGolden = false; |
| + |
| +#ifndef CONFIG_SBE_UPDATE_SEQUENTIAL |
| + do |
| + { |
| + // Get the master processor |
| + TARGETING::Target * l_masterProc = NULL; |
| + TARGETING::targetService().masterProcChipTargetHandle(l_masterProc); |
| + assert( l_masterProc != NULL ); |
| + |
| + sbeSeepromSide_t l_currentSide = SBE_SEEPROM_INVALID; |
| + |
| + // Get Seeprom side |
| + l_errl = getSbeBootSeeprom(l_masterProc, l_currentSide); |
| + |
| + if( l_errl ) |
| + { |
| + TRACFCOMP( g_trac_sbe, ERR_MRK |
| + "isGoldenSide() - Error returned " |
| + "from getSbeBootSeeprom() " |
| + "rc=0x%.4X, Target UID=0x%X", |
| + l_errl->reasonCode(), |
| + TARGETING::get_huid(l_masterProc)); |
| + break; |
| + } |
| + |
| + //Get PNOR Side |
| + PNOR::SideId l_pnorSide = PNOR::WORKING; |
| + PNOR::SideInfo_t l_sideInfo; |
| + |
| + l_errl = PNOR::getSideInfo( l_pnorSide, l_sideInfo ); |
| + |
| + if( l_errl ) |
| + { |
| + TRACFCOMP(g_trac_sbe, ERR_MRK |
| + "isGoldenSide() - Error returned " |
| + "from PNOR::getSideInfo() " |
| + "rc=0x%.4X, Target UID=0x%X", |
| + l_errl->reasonCode(), |
| + TARGETING::get_huid( l_masterProc )); |
| + break; |
| + } |
| + |
| + // SBE_SEEPROM1 by itself does not imply golden side. |
| + // cross reference sbe side with pnor side to make sure. |
| + if(( l_currentSide == SBE_SEEPROM1 ) && |
| + (( l_sideInfo.isGolden ) || (l_sideInfo.hasOtherSide == false ))) |
| + { |
| + TRACUCOMP(g_trac_sbe, INFO_MRK |
| + "sbe_update.C::isGoldenSide() - " |
| + "Booted from Golden side!"); |
| + o_isGolden = true; |
| + } |
| + |
| + }while( 0 ); |
| +#endif |
| + return l_errl; |
| + } |
| |
| |
| ///////////////////////////////////////////////////////////////////// |
| diff --git a/src/usr/targeting/common/target.C b/src/usr/targeting/common/target.C |
| index 2248283..559fd4e 100644 |
| --- a/src/usr/targeting/common/target.C |
| +++ b/src/usr/targeting/common/target.C |
| @@ -645,6 +645,53 @@ bool Target::uninstallWriteAttributeCallback() |
| #undef TARG_FN |
| } |
| |
| + |
| +//****************************************************************************** |
| +// setFrequencyAttributes |
| +//****************************************************************************** |
| +void setFrequencyAttributes(Target * i_sys, uint32_t i_newNestFreq) |
| +{ |
| + |
| + // Calculate the new value for PIB_I2C_NEST_PLL using old freq attributes. |
| + uint32_t l_oldPll = i_sys->getAttr<TARGETING::ATTR_PIB_I2C_NEST_PLL>(); |
| + uint32_t l_oldNestFreq = i_sys->getAttr<TARGETING::ATTR_NEST_FREQ_MHZ>(); |
| + uint32_t l_newPll = (i_newNestFreq * l_oldPll)/l_oldNestFreq; |
| + |
| + //NEST_FREQ |
| + i_sys->setAttr<TARGETING::ATTR_NEST_FREQ_MHZ>(i_newNestFreq); |
| + TRACFCOMP(g_trac_targeting, |
| + "ATTR_NEST_FREQ_MHZ getting set from %d to %d", |
| + l_oldNestFreq, |
| + i_newNestFreq ); |
| + |
| + //FREQ_X |
| + uint32_t l_freqX = i_newNestFreq * 2; |
| + i_sys->setAttr<TARGETING::ATTR_FREQ_X>(l_freqX); |
| + TRACFCOMP(g_trac_targeting, |
| + "ATTR_FREQ_X getting set to from %d to %d", |
| + l_oldNestFreq*2, |
| + l_freqX ); |
| + |
| + //FREQ_PB |
| + uint32_t l_freqPb = i_newNestFreq; |
| + i_sys->setAttr<TARGETING::ATTR_FREQ_PB>(l_freqPb); |
| + TRACFCOMP(g_trac_targeting, |
| + "ATTR_FREQ_PB getting set from %d to %d", |
| + l_oldNestFreq, |
| + l_freqPb ); |
| + |
| + //PIB_I2C_NEST_PLL |
| + i_sys->setAttr<TARGETING::ATTR_PIB_I2C_NEST_PLL>(l_newPll); |
| + TRACFCOMP(g_trac_targeting, |
| + "ATTR_PIB_I2C_NEST_PLL getting set from %x to %x", |
| + l_oldPll, |
| + l_newPll); |
| + |
| + return; |
| +} |
| + |
| + |
| + |
| //****************************************************************************** |
| // Attribute Tanks |
| //****************************************************************************** |
| diff --git a/src/usr/targeting/common/xmltohb/attribute_types.xml b/src/usr/targeting/common/xmltohb/attribute_types.xml |
| index 05497fd..88041b4 100644 |
| --- a/src/usr/targeting/common/xmltohb/attribute_types.xml |
| +++ b/src/usr/targeting/common/xmltohb/attribute_types.xml |
| @@ -2049,6 +2049,7 @@ |
| <simpleType><uint32_t></uint32_t></simpleType> |
| <persistency>non-volatile</persistency> |
| <readable/> |
| + <writeable/> |
| <hwpfToHbAttrMap> |
| <id>ATTR_FREQ_PB</id> |
| <macro>DIRECT</macro> |
| @@ -2083,6 +2084,7 @@ |
| <simpleType><uint32_t></uint32_t></simpleType> |
| <persistency>non-volatile</persistency> |
| <readable/> |
| + <writeable/> |
| <hwpfToHbAttrMap> |
| <id>ATTR_FREQ_X</id> |
| <macro>DIRECT</macro> |
| @@ -6103,7 +6105,7 @@ firmware notes: Used as override attribute for pstate procedure |
| <default>2000</default> |
| </uint32_t> |
| </simpleType> |
| - <persistency>volatile</persistency> |
| + <persistency>non-volatile</persistency> |
| <readable/> |
| <writeable/> |
| <hwpfToHbAttrMap> |
| @@ -15666,7 +15668,7 @@ firmware notes: Platforms should initialize this attribute to AUTO (0)</descript |
| |
| <attribute> |
| <id>MRW_VMEM_REGULATOR_POWER_LIMIT_PER_DIMM_ADJ_ENABLE</id> |
| - <description>Machine Readable Workbook enablement of the HWP code to adjust |
| + <description>Machine Readable Workbook enablement of the HWP code to adjust |
| the VMEM regulator power limit based on number of installed DIMMs. |
| </description> |
| <simpleType> |
| @@ -15702,7 +15704,7 @@ firmware notes: Platforms should initialize this attribute to AUTO (0)</descript |
| |
| <attribute> |
| <id>MRW_VMEM_REGULATOR_MEMORY_POWER_LIMIT_PER_DIMM</id> |
| - <description>Machine Readable Workbook VMEM regulator power limit per CDIMM |
| + <description>Machine Readable Workbook VMEM regulator power limit per CDIMM |
| assuming a full configuration. Units in cW. |
| </description> |
| <simpleType> |
| @@ -15741,7 +15743,7 @@ firmware notes: Platforms should initialize this attribute to AUTO (0)</descript |
| |
| <attribute> |
| <id>MRW_NEST_CAPABLE_FREQUENCIES_SYS</id> |
| - <description>The NEST frequencies that the system can support. This is a bit-wise value that represents which of the possible nest frequencies are supported : 2.0GHz, 2.4GHz, or both. |
| + <description>The NEST frequencies that the system can support. This is a bit-wise value that represents which of the possible nest frequencies are supported. : 2.0GHz, 2.4GHz, or both. New frequencies should be added in ascending order. |
| </description> |
| <simpleType> |
| <enumeration> |
| -- |
| 1.8.2.2 |
| |