Skip to content

Commit

Permalink
Adds plug rule for dependent DIMM slots on Swift
Browse files Browse the repository at this point in the history
Change-Id: Ia528660b05e8a01186376dfaae26e6ea9258457b
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/89032
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: PPE CI <ppe-ci+hostboot@us.ibm.com>
Tested-by: HWSV CI <hwsv-ci+hostboot@us.ibm.com>
Reviewed-by: Mark Pizzutillo <mark.pizzutillo@ibm.com>
Reviewed-by: NICOLAS R FAJARDO <nicolas.fajardo@ibm.com>
Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com>
Reviewed-by: Jennifer A Stofer <stofer@us.ibm.com>
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/91336
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com>
Reviewed-by: Daniel M Crowell <dcrowell@us.ibm.com>
  • Loading branch information
Bradley Pepper authored and dcrowell77 committed Feb 25, 2020
1 parent 8e19c8c commit 504aa7f
Show file tree
Hide file tree
Showing 6 changed files with 274 additions and 5 deletions.
Expand Up @@ -99,8 +99,22 @@ posTraits<fapi2::TARGET_TYPE_MEM_PORT>::pos_type
relative_pos<fapi2::TARGET_TYPE_PROC_CHIP>(const fapi2::Target<fapi2::TARGET_TYPE_MEM_PORT>& i_target)
{
typedef mcTypeTraits<mc_type::EXPLORER> TT;
return fapi_pos(i_target) % (TT::PORTS_PER_OCMB * TT::OCMB_PER_OMI * TT::OMI_PER_MCC * TT::MCC_PER_MI * TT::MI_PER_MC *
TT::MC_PER_PROC);
return fapi_pos(i_target) % (TT::PORTS_PER_OCMB * TT::OCMB_PER_OMI * TT::OMI_PER_MCC * TT::MCC_PER_MI *
TT::MI_PER_MC * TT::MC_PER_PROC);
}

///
/// @brief Return an OCMB's relative position from a proc_chip
/// @param[in] i_target a target representing the target in question
/// @return The position relative to chiplet R
///
template<>
posTraits<fapi2::TARGET_TYPE_OCMB_CHIP>::pos_type
relative_pos<fapi2::TARGET_TYPE_PROC_CHIP>(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target)
{
typedef mcTypeTraits<mc_type::EXPLORER> TT;
return fapi_pos(i_target) % (TT::OCMB_PER_OMI * TT::OMI_PER_MCC * TT::MCC_PER_MI *
TT::MI_PER_MC * TT::MC_PER_PROC);
}

///
Expand Down
Expand Up @@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
/* Contributors Listed Below - COPYRIGHT 2020 */
/* Contributors Listed Below - COPYRIGHT 2019,2020 */
/* [+] International Business Machines Corp. */
/* */
/* */
Expand All @@ -22,3 +22,151 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */

///
/// @file p9a_plug_rules.C
/// @brief Enforcement of rules for plugging in DIMM
///
// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 3
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include <lib/shared/axone_consts.H>
#include <algorithm>

#include <generic/memory/lib/utils/assert_noexit.H>
#include <generic/memory/lib/utils/find.H>
#include <generic/memory/lib/utils/c_str.H>
#include <generic/memory/lib/utils/count_dimm.H>
#include <generic/memory/lib/utils/num.H>

#include <lib/plug_rules/p9a_plug_rules.H>

namespace mss
{

namespace plug_rule
{

///
/// @brief Helper function for channel_a_before_channel_b unit testing
/// @param[in] i_target ocmb chip target
/// @param[in] i_pos ocmb chip position
/// @param[in] i_ocmbs vector of all configured ocmb chips under proc chip
/// @param[out] o_channel_a_pos ocmb chip position
/// @param[out] o_pass true if plug rule passes, false otherwise
/// @return fapi2::FAPI2_RC_SUCCESS if okay
///
fapi2::ReturnCode channel_a_before_channel_b_helper(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
const uint64_t i_pos,
const std::vector<fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>>& i_ocmbs,
uint64_t& o_channel_a_pos,
bool& o_pass)
{
// Create a vector of the channel A position for each OCMB (according to Swift Design Workbook v1.1 29May2019.pdf)
static const std::vector<uint8_t> l_dependencies = {0, 0, 0, 2, 0, 6, 0, 4, 0, 9, 0, 11, 0, 12, 0, 14};
uint64_t l_dependency = 0;
auto l_ocmb_it = i_ocmbs.begin();

// Comparator lambda expression
const auto compare = [&l_dependency](const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_lhs)
{
return (mss::relative_pos<fapi2::TARGET_TYPE_PROC_CHIP>(i_lhs) == l_dependency);
};

FAPI_ASSERT(i_pos < mss::axone::MAX_DIMM_PER_PROC,
fapi2::MSS_OUT_OF_BOUNDS_INDEXING()
.set_TARGET(i_target)
.set_INDEX(i_pos)
.set_LIST_SIZE(l_dependencies.size())
.set_FUNCTION(mss::axone::CHANNEL_A_BEFORE_CHANNEL_B),
"%s has an invalid position index (%d)", mss::c_str(i_target), i_pos);

o_channel_a_pos = l_dependencies[i_pos];

// All even positions are channel A, so they are ok
if (!is_odd(i_pos))
{
o_pass = true;
return fapi2::FAPI2_RC_SUCCESS;
}

// Check the channel A dependency for i_pos
l_dependency = l_dependencies[i_pos];

// Find iterator to matching key (make sure OCMB for channel A is configured)
l_ocmb_it = std::find_if(i_ocmbs.begin(),
i_ocmbs.end(),
compare);

o_pass = l_ocmb_it != i_ocmbs.end();
return fapi2::FAPI2_RC_SUCCESS;

fapi_try_exit:
return fapi2::current_err;
}

///
/// @brief Enforce plug order dependencies
/// @param[in] i_target proc chip target
/// @return fapi2::FAPI2_RC_SUCCESS if okay
///
fapi2::ReturnCode channel_a_before_channel_b(const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target)
{
typedef mcTypeTraits<mc_type::EXPLORER> TT;

fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
const auto l_ocmbs = mss::find_targets<fapi2::TARGET_TYPE_OCMB_CHIP>(i_target);
const uint64_t l_pos_offset = mss::fapi_pos(i_target) *
(TT::OCMB_PER_OMI * TT::OMI_PER_MCC * TT::MCC_PER_MI * TT::MI_PER_MC * TT::MC_PER_PROC);

for ( const auto& l_ocmb : l_ocmbs )
{
// Find the position of the ocmb chip
const auto l_pos = mss::relative_pos<fapi2::TARGET_TYPE_PROC_CHIP>(l_ocmb);
uint64_t l_channel_a_pos = 0;
bool l_pass = false;

FAPI_TRY(channel_a_before_channel_b_helper(l_ocmb, l_pos, l_ocmbs, l_channel_a_pos, l_pass));

// Call out this OCMB if it's channel A partner is not configured
FAPI_ASSERT( l_pass,
fapi2::MSS_PLUG_RULES_SINGLE_DDIMM_IN_WRONG_SLOT()
.set_SLOT_POSITION(l_pos + l_pos_offset)
.set_CHANNEL_A_SLOT_POSITION(l_channel_a_pos + l_pos_offset)
.set_TARGET(l_ocmb),
"%s DDIMM is plugged into the wrong slot. Must plug into channel A slot first (%d)", mss::c_str(l_ocmb),
(l_channel_a_pos + l_pos_offset) );
}

fapi_try_exit:
return fapi2::current_err;
}

///
/// @brief Enforce the plug-rules we can do before mss_freq
/// @param[in] i_target FAPI2 target (proc chip)
/// @return fapi2::FAPI2_RC_SUCCESS if okay, otherwise a MSS_PLUG_RULE error code
///
fapi2::ReturnCode enforce_pre_freq(const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target)
{
// If there are no DIMM, we can just get out.
if (mss::count_dimm(mss::find_targets<fapi2::TARGET_TYPE_MEM_PORT>(i_target)) == 0)
{
FAPI_INF("Skipping plug rule check on %s because it has no DIMM configured", mss::c_str(i_target));
return fapi2::FAPI2_RC_SUCCESS;
}

// Check channel A versus B plug order dependencies
FAPI_TRY( channel_a_before_channel_b(i_target) );

fapi_try_exit:
return fapi2::current_err;
}

} // ns plug_rule

} // ns mss
Expand Up @@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
/* Contributors Listed Below - COPYRIGHT 2020 */
/* Contributors Listed Below - COPYRIGHT 2019,2020 */
/* [+] International Business Machines Corp. */
/* */
/* */
Expand All @@ -22,3 +22,59 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */

///
/// @file p9a_plug_rules.H
/// @brief Enforcement of rules for plugging in DIMM
///
// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 3
// *HWP Consumed by: FSP:HB

#ifndef _P9A_PLUG_RULES_H_
#define _P9A_PLUG_RULES_H_

#include <fapi2.H>
#include <generic/memory/lib/utils/pos.H>

namespace mss
{

namespace plug_rule
{

///
/// @brief Enforce the plug-rules we can do before mss_freq
/// @param[in] i_target FAPI2 target (proc chip)
/// @return fapi2::FAPI2_RC_SUCCESS if okay, otherwise a MSS_PLUG_RULE error code
///
fapi2::ReturnCode enforce_pre_freq(const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target);

///
/// @brief Enforce having Channel A plugged before Channel B
/// @param[in] i_target proc chip target
/// @return fapi2::FAPI2_RC_SUCCESS if okay
///
fapi2::ReturnCode channel_a_before_channel_b(const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target);

///
/// @brief Helper function for channel_a_before_channel_b unit testing
/// @param[in] i_target ocmb chip target
/// @param[in] i_pos ocmb chip position
/// @param[in] i_ocmbs vector of all configured ocmb chips under proc chip
/// @param[out] o_channel_a_pos ocmb chip position
/// @param[out] o_pass true if plug rule passes, false otherwise
/// @return fapi2::FAPI2_RC_SUCCESS if okay
///
fapi2::ReturnCode channel_a_before_channel_b_helper(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
const uint64_t i_pos,
const std::vector<fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>>& i_ocmbs,
uint64_t& o_channel_a_pos,
bool& o_pass);

} // ns plug_rule
} // ns mss

#endif // _P9A_PLUG_RULES_H_
Expand Up @@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
/* Contributors Listed Below - COPYRIGHT 2019 */
/* Contributors Listed Below - COPYRIGHT 2019,2020 */
/* [+] International Business Machines Corp. */
/* */
/* */
Expand Down Expand Up @@ -43,4 +43,28 @@ const uint8_t MAX_MC_SIDES_PER_PROC = 2; // MC01, MC23
const uint8_t MAX_MC_PER_PROC = 4; // MC0, MC1, MC2, MC3
const uint8_t MAX_MC_PER_SIDE = 2; // MC0, MC1 or MC2, MC3

namespace mss
{
namespace axone
{

///
/// @brief common axone sizes
///
enum sizes
{
MAX_DIMM_PER_PROC = 16,
};

///
/// @brief explorer ffdc codes
///
enum ffdc_codes
{
CHANNEL_A_BEFORE_CHANNEL_B = 0x9000,
};

} // axone
} // mss

#endif
6 changes: 6 additions & 0 deletions src/import/chips/p9a/procedures/hwp/memory/p9a_mss_freq.C
Expand Up @@ -48,6 +48,7 @@
#include <generic/memory/lib/utils/count_dimm.H>
#include <generic/memory/lib/utils/freq/gen_mss_freq.H>
#include <generic/memory/mss_git_data_helper.H>
#include <lib/plug_rules/p9a_plug_rules.H>

///
/// @brief Calculate and save off DIMM frequencies
Expand Down Expand Up @@ -94,6 +95,11 @@ fapi2::ReturnCode p9a_mss_freq( const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP

}

// Check plug rules.
FAPI_TRY( mss::plug_rule::enforce_pre_freq(i_target),
"Failed enforce_plug_rules for %s", mss::c_str(i_target) );

// Set frequency attributes
FAPI_TRY(mss::generate_freq<mss::proc_type::AXONE>(i_target));

fapi_try_exit:
Expand Down
21 changes: 21 additions & 0 deletions src/import/generic/procedures/xml/error_info/generic_error.xml
Expand Up @@ -1292,4 +1292,25 @@
</callout>
</hwpError>

<hwpError>
<rc>RC_MSS_PLUG_RULES_SINGLE_DDIMM_IN_WRONG_SLOT</rc>
<description>
A single DIMM was plugged into a secondary channel slot without
one plugged into the primary channel slot.
</description>
<ffdc>SLOT_POSITION</ffdc>
<ffdc>CHANNEL_A_SLOT_POSITION</ffdc>
<callout>
<procedure>MEMORY_PLUGGING_ERROR</procedure>
<priority>HIGH</priority>
</callout>
<callout>
<target>TARGET</target>
<priority>LOW</priority>
</callout>
<deconfigure>
<target>TARGET</target>
</deconfigure>
</hwpError>

</hwpErrors>

0 comments on commit 504aa7f

Please sign in to comment.