diff options
author | Stephen Glancy <sglancy@us.ibm.com> | 2017-10-02 09:02:35 -0500 |
---|---|---|
committer | Christian R. Geddes <crgeddes@us.ibm.com> | 2017-11-01 15:38:30 -0400 |
commit | 6b9bc4190d6086ec1384105e5579a09e1096e6c2 (patch) | |
tree | 7c3814c45055fb150e19d7a0ba129ab7946ea097 /src/import/chips/p9 | |
parent | 1439d34bee09985ff04ba661f56b388db935291f (diff) | |
download | talos-hostboot-6b9bc4190d6086ec1384105e5579a09e1096e6c2.tar.gz talos-hostboot-6b9bc4190d6086ec1384105e5579a09e1096e6c2.zip |
Updates memory plug rules
Plug rules to update
1) NO LRDIMM's allowed - currently not supported by code
2) No 3DS/non-3DS mixing - hardware workaround
3) No DRAM width mixing - from DRAM technical leadership
4) No hybrid/non-hybrid DIMM mixing
Change-Id: I5505e37a1ccd2b96860b4c1fef0fdaba0a7f9b21
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/47013
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Louis Stermole <stermole@us.ibm.com>
Reviewed-by: ANDRE A. MARIN <aamarin@us.ibm.com>
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: HWSV CI <hwsv-ci+hostboot@us.ibm.com>
Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com>
Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com>
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/47021
Reviewed-by: Christian R. Geddes <crgeddes@us.ibm.com>
Tested-by: Christian R. Geddes <crgeddes@us.ibm.com>
Diffstat (limited to 'src/import/chips/p9')
4 files changed, 356 insertions, 5 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/kind.H b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/kind.H index 907bd329b..048ec591d 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/kind.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/kind.H @@ -90,6 +90,8 @@ class kind iv_size = i_rhs.iv_size; iv_mfgid = i_rhs.iv_mfgid; iv_stack_type = i_rhs.iv_stack_type; + iv_hybrid = i_rhs.iv_hybrid; + iv_hybrid_memory_type = i_rhs.iv_hybrid_memory_type; return *this; } @@ -98,6 +100,7 @@ class kind /// @param[in] i_rhs the right hand side of the comparison statement /// @return bool true iff the two kind are of the same kind /// @warning this does not compare the targets (iv_target,) just the values + /// Also does not compare the mfgid as that's not really part of the DIMM kind but is additional information /// inline bool operator==(const kind& i_rhs) const { @@ -108,7 +111,10 @@ class kind (iv_dram_generation == i_rhs.iv_dram_generation) && (iv_dimm_type == i_rhs.iv_dimm_type) && (iv_rows == i_rhs.iv_rows) && - (iv_size == i_rhs.iv_size)); + (iv_size == i_rhs.iv_size) && + (iv_stack_type == i_rhs.iv_stack_type) && + (iv_hybrid == i_rhs.iv_hybrid) && + (iv_hybrid_memory_type == i_rhs.iv_hybrid_memory_type)); } /// @@ -139,6 +145,8 @@ class kind FAPI_TRY( mss::eff_dimm_size(i_target, iv_size) ); FAPI_TRY( mss::eff_dram_mfg_id(i_target, iv_mfgid) ); FAPI_TRY( mss::eff_prim_stack_type( i_target, iv_stack_type) ); + FAPI_TRY( mss::eff_hybrid( i_target, iv_hybrid )); + FAPI_TRY( mss::eff_hybrid_memory_type( i_target, iv_hybrid_memory_type )); return; fapi_try_exit: @@ -170,7 +178,9 @@ class kind const uint8_t i_rows, const uint32_t i_size, const uint16_t i_mfgid = 0, - const uint8_t i_stack_type = fapi2::ENUM_ATTR_EFF_PRIM_STACK_TYPE_SDP): + const uint8_t i_stack_type = fapi2::ENUM_ATTR_EFF_PRIM_STACK_TYPE_SDP, + const uint8_t i_hybrid = fapi2::ENUM_ATTR_EFF_HYBRID_NOT_HYBRID, + const uint8_t i_hybrid_memory_type = fapi2::ENUM_ATTR_EFF_HYBRID_MEMORY_TYPE_NONE): iv_target(0), iv_master_ranks(i_master_ranks), iv_total_ranks(i_total_ranks), @@ -182,7 +192,9 @@ class kind // TK consider calculating size rather than requiring it be set. iv_size(i_size), iv_mfgid(i_mfgid), - iv_stack_type(i_stack_type) + iv_stack_type(i_stack_type), + iv_hybrid(i_hybrid), + iv_hybrid_memory_type(i_hybrid_memory_type) { // Bit of an idiot-check to be sure a hand-crafted dimm::kind make sense wrt slaves, masters, packages, etc. // Both of these are checked in eff_config. If they are messed up, they should be caught there @@ -214,6 +226,8 @@ class kind uint32_t iv_size; uint16_t iv_mfgid; uint8_t iv_stack_type; + uint8_t iv_hybrid; + uint8_t iv_hybrid_memory_type; }; } diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/plug_rules.C b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/plug_rules.C index 26b391976..29689c59d 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/plug_rules.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/plug_rules.C @@ -55,6 +55,157 @@ namespace mss namespace plug_rule { +namespace code +{ + +/// +/// @brief Checks for invalid LRDIMM plug combinations +/// @param[in] i_kinds a vector of DIMM (sorted while procesing) +/// @return fapi2::FAPI2_RC_SUCCESS if no LRDIMM, otherwise a MSS_PLUG_RULE error code +/// @note This function will commit error logs representing the mixing failure +/// +fapi2::ReturnCode check_lrdimm( const std::vector<dimm::kind>& i_kinds ) +{ + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + + // If we have 0 DIMMs on the port, we don't care + for(const auto& l_kind : i_kinds) + { + FAPI_ASSERT( l_kind.iv_dimm_type != fapi2::ENUM_ATTR_EFF_DIMM_TYPE_LRDIMM, + fapi2::MSS_PLUG_RULES_LRDIMM_UNSUPPORTED() + .set_DIMM_TARGET(l_kind.iv_target), + "%s has an LRDIMM plugged and is currently unsupported", + mss::c_str(l_kind.iv_target) ); + } + +fapi_try_exit: + return fapi2::current_err; +} + +} // code + +/// +/// @brief Enforce DRAM width checks +/// @note DIMM0's width needs to equal DIMM1's width +/// @param[in] i_target the port +/// @param[in] i_kinds a vector of DIMM (sorted while processing) +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note Expects the kind array to represent the DIMM on the port. +/// +fapi2::ReturnCode check_dram_width(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const std::vector<dimm::kind>& i_kinds) +{ + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + + // Only do this check if we have the maximum number DIMM kinds + if(i_kinds.size() == MAX_DIMM_PER_PORT) + { + FAPI_ASSERT( i_kinds[0].iv_dram_width == i_kinds[1].iv_dram_width, + fapi2::MSS_PLUG_RULES_INVALID_DRAM_WIDTH_MIX() + .set_DIMM_SLOT_ZERO(i_kinds[0].iv_dram_width) + .set_DIMM_SLOT_ONE(i_kinds[1].iv_dram_width) + .set_MCA_TARGET(i_target), + "%s has DIMM's with two different DRAM widths installed of type %d and of type %d. Cannot mix DIMM of different widths on a single port", + mss::c_str(i_target), i_kinds[0].iv_dram_width, i_kinds[1].iv_dram_width ); + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Enforce hybrid DIMM checks +/// @note No hybrid/non-hybrid and no different hybrid types +/// @param[in] i_target the port +/// @param[in] i_kinds a vector of DIMM (sorted while processing) +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note Expects the kind array to represent the DIMM on the port. +/// +fapi2::ReturnCode check_hybrid(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const std::vector<dimm::kind>& i_kinds) +{ + // Make sure we don't get a stale error + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + + // Skip the below checks if we have less than the maximum number of DIMM's + if(i_kinds.size() < MAX_DIMM_PER_PORT) + { + return fapi2::FAPI2_RC_SUCCESS; + } + + // Assert that we do not have an error + FAPI_ASSERT( i_kinds[0].iv_hybrid == i_kinds[1].iv_hybrid, + fapi2::MSS_PLUG_RULES_INVALID_HYBRID_MIX() + .set_DIMM_SLOT_ZERO(i_kinds[0].iv_hybrid) + .set_DIMM_SLOT_ONE(i_kinds[1].iv_hybrid) + .set_MCA_TARGET(i_target), + "%s has DIMM's with two different hybrid types installed (type %d and type %d). Cannot mix DIMM of different hybrid types on a single port", + mss::c_str(i_target), i_kinds[0].iv_hybrid, i_kinds[1].iv_hybrid ); + + // Only do the below check if the DIMM's are hybrid DIMM's + if(i_kinds[0].iv_hybrid == fapi2::ENUM_ATTR_EFF_HYBRID_IS_HYBRID) + { + // Assert that we do not have an error + FAPI_ASSERT( i_kinds[0].iv_hybrid_memory_type == i_kinds[1].iv_hybrid_memory_type, + fapi2::MSS_PLUG_RULES_INVALID_HYBRID_MEMORY_TYPE_MIX() + .set_DIMM_SLOT_ZERO(i_kinds[0].iv_hybrid_memory_type) + .set_DIMM_SLOT_ONE(i_kinds[1].iv_hybrid_memory_type) + .set_MCA_TARGET(i_target), + "%s has DIMM's with two different hybrid memory types installed (type %d and type %d). Cannot mix DIMM of different hybrid memory types on a single port", + mss::c_str(i_target), i_kinds[0].iv_hybrid_memory_type, i_kinds[1].iv_hybrid_memory_type ); + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Enforce DRAM stack type checks +/// @note No 3DS and non-3DS DIMM's can mix +/// @param[in] i_target the port +/// @param[in] i_kinds a vector of DIMM (sorted while processing) +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note Expects the kind array to represent the DIMM on the port. +/// +fapi2::ReturnCode check_stack_type(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const std::vector<dimm::kind>& i_kinds) +{ + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + + // Only do this check if we have the maximum number DIMM kinds + if(i_kinds.size() == MAX_DIMM_PER_PORT) + { + // Only do the assert if we have any 3DS DIMM, as the chip bug is for mixed config between DIMM that use and do not use CID + // Note: we should be able to mix SDP and DDP ok, as both DIMM's do not use CID + const bool l_has_3ds = (i_kinds[0].iv_stack_type == fapi2::ENUM_ATTR_EFF_PRIM_STACK_TYPE_3DS) || + (i_kinds[1].iv_stack_type == fapi2::ENUM_ATTR_EFF_PRIM_STACK_TYPE_3DS); + + // We have an error if we have the below scenario of 3DS and the stack types not being equal + const auto l_error = l_has_3ds && i_kinds[0].iv_stack_type != i_kinds[1].iv_stack_type; + + FAPI_DBG("%s %s 3DS. Stack types are %s (%u,%u). configuration %s ok.", + mss::c_str(i_target), + l_has_3ds ? "has" : "does not have", + (i_kinds[0].iv_stack_type != i_kinds[1].iv_stack_type) ? "not equal" : "equal", + i_kinds[0].iv_stack_type, + i_kinds[1].iv_stack_type, + l_error ? "isn't" : "is" + ); + + // Assert that we do not have an error + FAPI_ASSERT( !l_error, + fapi2::MSS_PLUG_RULES_INVALID_STACK_TYPE_MIX() + .set_DIMM_SLOT_ZERO(i_kinds[0].iv_stack_type) + .set_DIMM_SLOT_ONE(i_kinds[1].iv_stack_type) + .set_MCA_TARGET(i_target), + "%s has DIMM's with two different stack types installed (type %d and type %d). Cannot mix DIMM of different stack types on a single port", + mss::c_str(i_target), i_kinds[0].iv_stack_type, i_kinds[1].iv_stack_type ); + } + +fapi_try_exit: + return fapi2::current_err; +} + /// /// @brief Helper to evaluate the unsupported rank config override attribute /// @param[in] i_dimm0_ranks count of the ranks on DIMM in slot 0 @@ -63,7 +214,8 @@ namespace plug_rule /// @return true iff this rank config is supported according to the unsupported attribute /// @note not to be used to enforce populated/unpopulated - e.g., 0 ranks in both slots is ignored /// -bool unsupported_rank_helper(const uint64_t i_dimm0_ranks, const uint64_t i_dimm1_ranks, +bool unsupported_rank_helper(const uint64_t i_dimm0_ranks, + const uint64_t i_dimm1_ranks, const fapi2::buffer<uint64_t>& i_attr) { // Quick - if the attribute is 0 (typically is) then we're out. @@ -497,6 +649,18 @@ fapi2::ReturnCode plug_rule::enforce_plug_rules(const fapi2::Target<fapi2::TARGE // to check here. FAPI_TRY( plug_rule::check_rank_config(i_target, l_dimm_kinds, l_ranks_override) ); + // Ensures that the port has a valid combination of DRAM widths + FAPI_TRY( plug_rule::check_dram_width(i_target, l_dimm_kinds) ); + + // Ensures that the port has a valid combination of stack types + FAPI_TRY( plug_rule::check_stack_type(i_target, l_dimm_kinds) ); + + // Ensures that the port has a valid combination of hybrid DIMM + FAPI_TRY( plug_rule::check_hybrid(i_target, l_dimm_kinds) ); + + // Checks to see if any DIMM are LRDIMM + FAPI_TRY( plug_rule::code::check_lrdimm(l_dimm_kinds) ); + fapi_try_exit: return fapi2::current_err; } diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/plug_rules.H b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/plug_rules.H index 5ac502b09..d258f2c71 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/plug_rules.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/plug_rules.H @@ -69,7 +69,8 @@ fapi2::ReturnCode enforce_plug_rules(const fapi2::Target<fapi2::TARGET_TYPE_MCA> /// @return true iff this rank config is supported according to the unsupported attribute /// @note not to be used to enforce populated/unpopulated - e.g., 0 ranks in both slots is ignored /// -bool unsupported_rank_helper(const uint64_t i_dimm0_ranks, const uint64_t i_dimm1_ranks, +bool unsupported_rank_helper(const uint64_t i_dimm0_ranks, + const uint64_t i_dimm1_ranks, const fapi2::buffer<uint64_t>& i_attr); /// /// @brief Enforces the DEAD LOAD rules @@ -148,6 +149,53 @@ fapi2::ReturnCode check_rank_config(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& const std::vector<dimm::kind>& i_kinds, const uint64_t i_ranks_override); +/// +/// @brief Enforce DRAM width checks +/// @note DIMM0's width needs to equal DIMM1's width +/// @param[in] i_target the port +/// @param[in] i_kinds a vector of DIMM (sorted while processing) +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note Expects the kind array to represent the DIMM on the port. +/// +fapi2::ReturnCode check_dram_width(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const std::vector<dimm::kind>& i_kinds); + +/// +/// @brief Enforce DRAM stack type checks +/// @note No 3DS and non-3DS DIMM's can mix +/// @param[in] i_target the port +/// @param[in] i_kinds a vector of DIMM (sorted while processing) +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note Expects the kind array to represent the DIMM on the port. +/// +fapi2::ReturnCode check_stack_type(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const std::vector<dimm::kind>& i_kinds); + +/// +/// @brief Enforce hybrid DIMM checks +/// @note No hybrid/non-hybrid and no different hybrid types +/// @param[in] i_target the port +/// @param[in] i_kinds a vector of DIMM (sorted while processing) +/// @return fapi2::FAPI2_RC_SUCCESS if okay +/// @note Expects the kind array to represent the DIMM on the port. +/// +fapi2::ReturnCode check_hybrid(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const std::vector<dimm::kind>& i_kinds); + +// Adding in code based plug rules - as supporting code gets added, the following checks can be deleted +namespace code +{ + +/// +/// @brief Checks for invalid LRDIMM plug combinations +/// @param[in] i_kinds a vector of DIMM (sorted while procesing) +/// @return fapi2::FAPI2_RC_SUCCESS if no LRDIMM, otherwise a MSS_PLUG_RULE error code +/// @note This function will commit error logs representing the mixing failure +/// +fapi2::ReturnCode check_lrdimm( const std::vector<dimm::kind>& i_kinds ); + +} // code + } // plug_rule } // mss diff --git a/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_plug_rules.xml b/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_plug_rules.xml index 9ee12499e..9c8f265e2 100644 --- a/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_plug_rules.xml +++ b/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_plug_rules.xml @@ -59,6 +59,131 @@ </hwpError> <hwpError> + <rc>RC_MSS_PLUG_RULES_INVALID_DRAM_WIDTH_MIX</rc> + <description> + Two different widths of DIMMs are installed on port + </description> + <ffdc>DIMM_SLOT_ZERO</ffdc> + <ffdc>DIMM_SLOT_ONE</ffdc> + <callout> + <procedure>MEMORY_PLUGGING_ERROR</procedure> + <priority>HIGH</priority> + </callout> + <callout> + <childTargets> + <parent>MCA_TARGET</parent> + <childType>TARGET_TYPE_DIMM</childType> + </childTargets> + <priority>MEDIUM</priority> + </callout> + <deconfigure> + <childTargets> + <parent>MCA_TARGET</parent> + <childType>TARGET_TYPE_DIMM</childType> + </childTargets> + </deconfigure> + </hwpError> + + <hwpError> + <rc>RC_MSS_PLUG_RULES_INVALID_STACK_TYPE_MIX</rc> + <description> + Two DIMMs with incompatable stack types are installed on port + </description> + <ffdc>DIMM_SLOT_ZERO</ffdc> + <ffdc>DIMM_SLOT_ONE</ffdc> + <callout> + <procedure>MEMORY_PLUGGING_ERROR</procedure> + <priority>HIGH</priority> + </callout> + <callout> + <childTargets> + <parent>MCA_TARGET</parent> + <childType>TARGET_TYPE_DIMM</childType> + </childTargets> + <priority>MEDIUM</priority> + </callout> + <deconfigure> + <childTargets> + <parent>MCA_TARGET</parent> + <childType>TARGET_TYPE_DIMM</childType> + </childTargets> + </deconfigure> + </hwpError> + + <hwpError> + <rc>RC_MSS_PLUG_RULES_INVALID_HYBRID_MIX</rc> + <description> + Two DIMMs with incompatable hybrid types are plugged + </description> + <ffdc>DIMM_SLOT_ZERO</ffdc> + <ffdc>DIMM_SLOT_ONE</ffdc> + <callout> + <procedure>MEMORY_PLUGGING_ERROR</procedure> + <priority>HIGH</priority> + </callout> + <callout> + <childTargets> + <parent>MCA_TARGET</parent> + <childType>TARGET_TYPE_DIMM</childType> + </childTargets> + <priority>MEDIUM</priority> + </callout> + <deconfigure> + <childTargets> + <parent>MCA_TARGET</parent> + <childType>TARGET_TYPE_DIMM</childType> + </childTargets> + </deconfigure> + </hwpError> + + <hwpError> + <rc>RC_MSS_PLUG_RULES_INVALID_HYBRID_MEMORY_TYPE_MIX</rc> + <description> + Two DIMMs with incompatable hybrid memory types + </description> + <ffdc>DIMM_SLOT_ZERO</ffdc> + <ffdc>DIMM_SLOT_ONE</ffdc> + <callout> + <procedure>MEMORY_PLUGGING_ERROR</procedure> + <priority>HIGH</priority> + </callout> + <callout> + <childTargets> + <parent>MCA_TARGET</parent> + <childType>TARGET_TYPE_DIMM</childType> + </childTargets> + <priority>MEDIUM</priority> + </callout> + <deconfigure> + <childTargets> + <parent>MCA_TARGET</parent> + <childType>TARGET_TYPE_DIMM</childType> + </childTargets> + </deconfigure> + </hwpError> + + <hwpError> + <rc>RC_MSS_PLUG_RULES_LRDIMM_UNSUPPORTED</rc> + <description> + The DIMM is an LRDIMM and that is currently not supported + </description> + <callout> + <procedure>MEMORY_PLUGGING_ERROR</procedure> + <priority>HIGH</priority> + </callout> + <callout> + <target>DIMM_TARGET</target> + <priority>MEDIUM</priority> + </callout> + <deconfigure> + <target>DIMM_TARGET</target> + </deconfigure> + <gard> + <target>DIMM_TARGET</target> + </gard> + </hwpError> + + <hwpError> <rc>RC_MSS_DEAD_LOAD_ON_PORT</rc> <description> A DIMM is deconfigured on a dual-drop port that has two DIMMS installed |