summaryrefslogtreecommitdiffstats
path: root/src/import/chips/p9/procedures/hwp/memory/lib
diff options
context:
space:
mode:
authorStephen Glancy <sglancy@us.ibm.com>2017-10-02 09:02:35 -0500
committerChristian R. Geddes <crgeddes@us.ibm.com>2017-11-01 15:38:30 -0400
commit6b9bc4190d6086ec1384105e5579a09e1096e6c2 (patch)
tree7c3814c45055fb150e19d7a0ba129ab7946ea097 /src/import/chips/p9/procedures/hwp/memory/lib
parent1439d34bee09985ff04ba661f56b388db935291f (diff)
downloadtalos-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/procedures/hwp/memory/lib')
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/dimm/kind.H20
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/eff_config/plug_rules.C166
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/eff_config/plug_rules.H50
3 files changed, 231 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
OpenPOWER on IntegriCloud