From 3c3ab2bd4c3cbee67eb518bcce214234d8f071f3 Mon Sep 17 00:00:00 2001 From: Alvin Wang Date: Thu, 14 Mar 2019 10:25:31 -0500 Subject: Move MCBIST lib to generic folder Change-Id: Ib717742707bea6a626131578f5a3b1aeebc76281 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/69677 Tested-by: Jenkins Server Tested-by: PPE CI Tested-by: FSP CI Jenkins Tested-by: HWSV CI Dev-Ready: STEPHEN GLANCY Tested-by: Hostboot CI Reviewed-by: Louis Stermole Reviewed-by: STEPHEN GLANCY Reviewed-by: Jennifer A. Stofer Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/69707 Reviewed-by: Zane C. Shelley Reviewed-by: Christian R. Geddes Tested-by: Christian R. Geddes --- .../p9/procedures/hwp/memory/lib/mcbist/memdiags.C | 597 +-------------------- 1 file changed, 12 insertions(+), 585 deletions(-) (limited to 'src/import/chips/p9/procedures/hwp/memory/lib/mcbist/memdiags.C') diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/memdiags.C b/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/memdiags.C index b235637b5..682226cfd 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/memdiags.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/memdiags.C @@ -33,26 +33,17 @@ // *HWP Level: 3 // *HWP Consumed by: FSP:HB -#include #include +#include #include #include #include #include #include -#include -#include -#include #include #include -using fapi2::TARGET_TYPE_MCBIST; -using fapi2::TARGET_TYPE_MCA; -using fapi2::TARGET_TYPE_DIMM; -using fapi2::TARGET_TYPE_SYSTEM; -using fapi2::FAPI2_RC_SUCCESS; -using fapi2::FAPI2_RC_INVALID_PARAMETER; namespace mss { @@ -60,165 +51,17 @@ namespace mss namespace memdiags { -/// -/// @brief Stop the current command -/// @param[in] i_target the target -/// @return FAPI2_RC_SUCCESS iff ok -/// -template<> -fapi2::ReturnCode stop( const fapi2::Target& i_target ) -{ - // Too long, make shorter - using TT = mss::mcbistTraits; - - // Poll parameters are defined as TK so that we wait a nice time for operations - // For now use the defaults - mss::poll_parameters l_poll_parameters; - fapi2::buffer l_status; - fapi2::buffer l_last_address; - bool l_poll_result = false; - - FAPI_INF("Stopping any mcbist operations which are in progress for %s", mss::c_str(i_target)); - - // TODO RTC:153951 Add masking of FIR when stopping - FAPI_TRY( mss::mcbist::start_stop(i_target, mss::STOP) ); - - // Poll waiting for the engine to stop - l_poll_result = mss::poll(i_target, TT::STATQ_REG, l_poll_parameters, - [&l_status](const size_t poll_remaining, const fapi2::buffer& stat_reg) -> bool - { - FAPI_DBG("looking for mcbist not in-progress, mcbist statq 0x%llx, remaining: %d", stat_reg, poll_remaining); - l_status = stat_reg; - // We're done polling when either we see we're in progress or we see we're done. - return l_status.getBit() == false; - }); - - // Pass or fail output the current address. This is useful for debugging when we can get it. - // It's in the register FFDC for memdiags so we don't need it below - FAPI_TRY( mss::getScom(i_target, TT::LAST_ADDR_REG, l_last_address) ); - FAPI_INF("MCBIST last address (during stop): 0x%016lx for %s", - l_last_address, mss::c_str(i_target)); - - // So we've either stopped or we timed out - FAPI_ASSERT( l_poll_result == true, - fapi2::MSS_MEMDIAGS_MCBIST_FAILED_TO_STOP() - .set_MCBIST_TARGET(i_target) - .set_POLL_COUNT(l_poll_parameters.iv_poll_count), - "%s The MCBIST engine failed to stop its program", - mss::c_str(i_target) ); - -fapi_try_exit: - return fapi2::current_err; - -} - -/// -/// @brief memdiags init helper -/// Initializes common sections. Broken out rather than the base class ctor to enable checking return codes -/// in subclassed constructors more easily. -/// @return FAPI2_RC_SUCCESS iff everything ok -/// -template<> -fapi2::ReturnCode operation::base_init() -{ - FAPI_INF("memdiags base init for %s", mss::c_str(iv_target)); - - // Check the state of the MCBIST engine to make sure its OK that we proceed. - // Force stop the engine (per spec, as opposed to waiting our turn) - FAPI_TRY( memdiags::stop(iv_target) ); - - // Zero out cmd timebase - mcbist::program constructor does that for us. - // Load pattern - FAPI_TRY( iv_program.change_pattern(iv_const.iv_pattern) ); - - // Load end boundaries - iv_program.change_end_boundary(iv_const.iv_end_boundary); - - // Load thresholds - iv_program.change_thresholds(iv_const.iv_stop); - - // Setup the requested speed - FAPI_TRY( iv_program.change_speed(iv_target, iv_const.iv_speed) ); - - // Enable maint addressing mode - enabled by default in the mcbist::program ctor - - // Apparently the MCBIST engine needs the ports selected even though the ports are specified - // in the subtest. We can just select them all, and it adjusts when it executes the subtest - iv_program.select_ports(0b1111); - - // Kick it off, don't wait for a result - iv_program.change_async(mss::ON); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Single port initializer -/// Initializes common sections. Broken out rather than the base class ctor to enable checking return codes -/// in subclassed constructors more easily. -/// @return FAPI2_RC_SUCCESS iff everything ok -/// -template<> -fapi2::ReturnCode operation::single_port_init() -{ - FAPI_INF("single port init for %s", mss::c_str(iv_target)); - - const uint64_t l_relative_port_number = iv_const.iv_start_address.get_port(); - const uint64_t l_dimm_number = iv_const.iv_start_address.get_dimm(); - - // Make sure the specificed port is functional - FAPI_ASSERT( mss::is_functional(iv_target, l_relative_port_number), - fapi2::MSS_MEMDIAGS_PORT_NOT_FUNCTIONAL() - .set_RELATIVE_PORT_POSITION(l_relative_port_number) - .set_ADDRESS( uint64_t(iv_const.iv_start_address) ) - .set_MCBIST_TARGET(iv_target), - "Port with relative postion %d is not functional for %s", - l_relative_port_number, mss::c_str(iv_target)); - - // No broadcast mode for this one - // Push on a read subtest - { - mss::mcbist::subtest_t l_subtest = iv_subtest; - - l_subtest.enable_port(l_relative_port_number); - l_subtest.enable_dimm(l_dimm_number); - iv_program.iv_subtests.push_back(l_subtest); - FAPI_INF("%s adding subtest 0x%04x for port %d, DIMM %d", - mss::c_str(iv_target), l_subtest, l_relative_port_number, l_dimm_number); - } - - // The address should have the port and DIMM noted in it. All we need to do is calculate the - // remainder of the address - if (iv_sim) - { - iv_const.iv_start_address.get_sim_end_address(iv_const.iv_end_address); - } - else if (iv_const.iv_end_address == mss::mcbist::address::LARGEST_ADDRESS) - { - // Only the DIMM range as we don't want to cross ports. - iv_const.iv_start_address.get_range(iv_const.iv_end_address); - } - - // Configure the address range - FAPI_TRY( mss::mcbist::config_address_range0(iv_target, iv_const.iv_start_address, iv_const.iv_end_address) ); - - // Initialize the common sections - FAPI_TRY( base_init() ); - -fapi_try_exit: - return fapi2::current_err; -} - /// /// @brief Helper to encapsualte the setting of multi-port address configurations /// @return FAPI2_RC_SUCCESS iff ok /// template<> -fapi2::ReturnCode operation::multi_port_addr() +fapi2::ReturnCode operation::multi_port_addr() { + using TT = mcbistTraits<>; + mss::mcbist::address l_end_of_start_port; - mss::mcbist::address l_end_of_complete_port(mss::mcbist::address::LARGEST_ADDRESS); + mss::mcbist::address l_end_of_complete_port(TT::LARGEST_ADDRESS); mss::mcbist::address l_start_of_end_port; // The last address in the start port is the start address thru the "DIMM range" (all addresses left on this DIMM) @@ -255,8 +98,8 @@ fapi_try_exit: /// @param[in] i_dimms a vector of DIMM targets /// template<> -void operation::configure_multiport_subtests(const - std::vector>& i_dimms) +void operation::configure_multiport_subtests( + const std::vector>& i_dimms) { // Constexpr's to beautify the code constexpr uint64_t FIRST_ADDRESS = 0; @@ -424,37 +267,21 @@ fapi_try_exit: } /// -/// @brief memdiags multi-port init helper +/// @brief memdiags multi-port init /// Initializes common sections. Broken out rather than the base class ctor to enable checking return codes /// in subclassed constructors more easily. /// @return FAPI2_RC_SUCCESS iff everything ok /// template<> -fapi2::ReturnCode operation::multi_port_init() +fapi2::ReturnCode operation::multi_port_init_internal() { - FAPI_INF("multi-port init for %s", mss::c_str(iv_target)); + FAPI_INF("multi-port init internal for %s", mss::c_str(iv_target)); - const auto l_mcas = mss::find_targets(iv_target); - - // Make sure we have ports, if we don't then exit out - if(l_mcas.size() == 0) - { - // Cronus can have no ports under an MCBIST, FW deconfigures by association - FAPI_INF("%s has no attached MCAs skipping setup", mss::c_str(iv_target)); - return fapi2::FAPI2_RC_SUCCESS; - } // Let's assume we are going to send out all subtest unless we are in broadcast mode, // where we only send up to 2 subtests under an MCA ( 1 for each DIMM) which is why no const auto l_dimms = mss::find_targets(iv_target); - if( l_dimms.size() == 0) - { - // Cronus can have no DIMMS under an MCBIST, FW deconfigures by association - FAPI_INF("%s has no attached DIMMs skipping setup", mss::c_str(iv_target)); - return fapi2::FAPI2_RC_SUCCESS; - } - // Get the port/DIMM information for the addresses. This is an integral value which allows us to index // all the DIMM across a controller. const uint64_t l_portdimm_start_address = iv_const.iv_start_address.get_port_dimm(); @@ -532,407 +359,7 @@ fapi_try_exit: return fapi2::current_err; } -/// -/// @brief memdiags::continuous_scrub_operation constructor -/// @param[in] i_target the target of the mcbist engine -/// @param[in] i_const the contraints of the operation -/// @param[out] o_rc the fapi2::ReturnCode of the intialization process -/// -template<> -continuous_scrub_operation::continuous_scrub_operation( - const fapi2::Target& i_target, - const constraints i_const, - fapi2::ReturnCode& o_rc ): - operation(i_target, mss::mcbist::scrub_subtest(), i_const) -{ - mss::mcbist::address l_generic_start_address; - mss::mcbist::address l_generic_end_address; - - FAPI_INF("setting up for continuous scrub for %s", mss::c_str(i_target)); - - // Scrub operations run 128B - iv_program.change_len64(mss::OFF); - - // We build a little program here which allows us to restart the loop in the event of a pause. - // So we need to craft some of the address ranges and some of the subtests by hand. - - // Setup address config 0 to cover all the addresses for a port/dimm. - // We leverage the MCBIST's ability to skip invalid addresses, and just setup - // If we're running in the simulator, we want to only touch the addresses which training touched - // *INDENT-OFF* - iv_sim ? - l_generic_start_address.get_sim_end_address(l_generic_end_address) : - l_generic_start_address.get_range(l_generic_end_address); - // *INDENT-ON* - - FAPI_TRY( mss::mcbist::config_address_range0(i_target, l_generic_start_address, l_generic_end_address) ); - - // We push on a fake subtest 0 and subtest 1. We fix them up after we fill in the - // rest of the subtests. - iv_program.iv_subtests.push_back(iv_subtest); - iv_program.iv_subtests.push_back(iv_subtest); - - // a generic 0 - DIMM address range. - // - // Subtests 2-9: One subtest per port/dimm each covering the whole range of that - // port/dimm. scrub_subtests by default are using address config 0, so each of - // these get their full address complement. - for (const auto& p : iv_target.template getChildren()) - { - for (const auto& d : p.template getChildren()) - { - // Don't destroy the subtest passed in, copy it - auto l_subtest = iv_subtest; - - l_subtest.enable_port(mss::relative_pos(p)); - l_subtest.enable_dimm(mss::index(d)); - iv_program.iv_subtests.push_back(l_subtest); - FAPI_INF("adding scrub subtest for %s (dimm %d) ( 0x%04x)", mss::c_str(d), mss::index(d), l_subtest); - } - } - - // - // Subtest 10: goto subtest 2. This causes us to loop back to the first port/dimm and go thru them all - // This subtest will be marked the last when the MCBMR registers are filled in. - // - iv_program.iv_subtests.push_back(mss::mcbist::goto_subtest(2)); - FAPI_INF("last goto subtest (10) is going to subtest 2 ( 0x%04x) for %s", iv_program.iv_subtests[2], - mss::c_str(iv_target)); - - // Ok, now we can go back in to fill in the first two subtests. - - { - auto l_subtest = iv_subtest; - auto l_port = iv_const.iv_start_address.get_port(); - auto l_dimm = iv_const.iv_start_address.get_dimm(); - size_t l_index = 2; - - // By default if we don't find our port/dimm in the subtests, we just go back to the beginning. - uint64_t l_goto_subtest = 2; - - // - // subtest 0 - // - - // load the start address given and calculate the end address. Stick this into address config 1 - // We don't need to account for the simulator here as the caller can do that when they setup the - // start address. - // *INDENT-OFF* - iv_sim ? - iv_const.iv_start_address.get_sim_end_address(iv_const.iv_end_address) : - iv_const.iv_start_address.get_range(iv_const.iv_end_address); - // *INDENT-ON* - - FAPI_TRY( mss::mcbist::config_address_range1(i_target, iv_const.iv_start_address, iv_const.iv_end_address) ); - - // We need to use this address range. We know it's ok to write to element 0 as we pushed it on above - l_subtest.change_addr_sel(1); - l_subtest.enable_port(l_port); - l_subtest.enable_dimm(l_dimm); - - iv_program.iv_subtests[0] = l_subtest; - FAPI_INF("adding scrub subtest 0 for port %d dimm %d (0x%04x) for %s", l_port, l_dimm, l_subtest, mss::c_str(i_target)); - - // - // subtest 1 - // - - // From the port/dimm specified in the start address, we know what subtest should execute next. The idea - // being that this 0'th subtest is a mechanism to allow the caller to start a scrub 'in the middle' and - // jump to the next port/dimm which would have been scrubbed. The hard part is that we don't know where - // in the subtest vector the 'next' port/dimm are placed. So we look for our port/dimm (skipping subtest 0 - // since we know that's us and skipping subtest 1 since it isn't there yet.) - for (; l_index < iv_program.iv_subtests.size(); ++l_index) - { - auto l_my_dimm = iv_program.iv_subtests[l_index].get_dimm(); - auto l_my_port = iv_program.iv_subtests[l_index].get_port(); - - if ((l_dimm == l_my_dimm) && (l_port == l_my_port)) - { - l_goto_subtest = l_index + 1; - break; - } - } - - // Since we set l_goto_subtest up with a meaningful default, we can just make a subtest with the - // l_goto_subtest subtest specified and pop that in to index 1. - FAPI_INF("adding scrub subtest 1 to goto subtest %d (port %d, dimm %d, test 0x%04x) for %s", l_goto_subtest, - iv_program.iv_subtests[l_goto_subtest].get_port(), - iv_program.iv_subtests[l_goto_subtest].get_dimm(), - iv_program.iv_subtests[l_goto_subtest], mss::c_str(i_target) ); - - iv_program.iv_subtests[1] = mss::mcbist::goto_subtest(l_goto_subtest); - } - - // Initialize the common sections - FAPI_TRY( base_init() ); - -fapi_try_exit: - o_rc = fapi2::current_err; - return; -} - -/// -/// @brief Super Fast Read Init - used to init all memory behind a target with a given pattern -/// @note Uses broadcast mode if possible -/// @param[in] i_target the target behind which all memory should be initialized -/// @param[in] i_pattern an index representing a pattern to use to initize memory (defaults to 0) -/// @return FAPI2_RC_SUCCESS iff everything ok -/// @note The function is asynchronous, and the caller should be looking for a done attention -/// -template<> -fapi2::ReturnCode sf_init( const fapi2::Target& i_target, - const uint64_t i_pattern ) -{ - FAPI_INF("superfast init start for %s", mss::c_str(i_target)); - - uint8_t l_sim = false; - FAPI_TRY( mss::is_simulation( l_sim) ); - - if (l_sim) - { - // Use some sort of pattern in sim in case the verification folks need to look for something - // TK. Need a verification pattern. This is a not-good pattern for verification ... We don't really - // have a good pattern for verification defined. - FAPI_INF("running mss sim init in place of sf_init for %s", mss::c_str(i_target)); - return mss::mcbist::sim::sf_init(i_target, i_pattern); - } - else - { - fapi2::ReturnCode l_rc; - constraints l_const(i_pattern); - sf_init_operation l_init_op(i_target, l_const, l_rc); - - FAPI_ASSERT( l_rc == FAPI2_RC_SUCCESS, - fapi2::MSS_MEMDIAGS_SUPERFAST_INIT_FAILED_TO_INIT().set_MCBIST_TARGET(i_target), - "Unable to initialize the MCBIST engine for a sf read %s", mss::c_str(i_target) ); - - return l_init_op.execute(); - } - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Super Fast Read to End of MCBIST - used to run superfast read on all memory behind the target -/// @tparam T the fapi2::TargetType of the target -/// @param[in] i_target the target behind which all memory should be read -/// @param[in] i_stop stop conditions -/// @param[in] i_address mcbist::address representing the address from which to start. -// Defaults to the first address behind the target -/// @param[in] i_end whether to end, and where -/// Defaults to stop after slave rank -/// @param[in] i_end_address mcbist::address representing the address to end. -// Defaults to mcbist::address::LARGEST_ADDRESS -/// @return FAPI2_RC_SUCCESS iff everything ok -/// @note The function is asynchronous, and the caller should be looking for a done attention -/// @note The address is often the port, dimm, rank but this is not enforced in the API. -/// -template<> -fapi2::ReturnCode sf_read( const fapi2::Target& i_target, - const stop_conditions& i_stop, - const mss::mcbist::address& i_address, - const end_boundary i_end, - const mss::mcbist::address& i_end_address ) -{ - FAPI_INF("superfast read - start for %s", mss::c_str(i_target)); - - fapi2::ReturnCode l_rc; - constraints l_const(i_stop, speed::LUDICROUS, i_end, i_address, i_end_address); - sf_read_operation l_read_op(i_target, l_const, l_rc); - - FAPI_ASSERT( l_rc == FAPI2_RC_SUCCESS, - fapi2::MSS_MEMDIAGS_SUPERFAST_READ_FAILED_TO_INIT().set_MCBIST_TARGET(i_target), - "Unable to initialize the MCBIST engine for a sf read %s", mss::c_str(i_target) ); - - return l_read_op.execute(); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Scrub - continuous scrub all memory behind the target -/// @param[in] i_target the target behind which all memory should be scrubbed -/// @param[in] i_stop stop conditions -/// @param[in] i_speed the speed to scrub -/// @param[in] i_address mcbist::address representing the port, dimm, rank -/// @return FAPI2_RC_SUCCESS iff everything ok -/// @warning The function is asynchronous, and the caller should be looking for a done attention -/// @note The operation will fail immediately when a stop condition is encountered -/// -template<> -fapi2::ReturnCode background_scrub( const fapi2::Target& i_target, - const stop_conditions& i_stop, - const speed i_speed, - const mss::mcbist::address& i_address ) -{ - FAPI_INF("continuous (background) scrub for %s", mss::c_str(i_target)); - - fapi2::ReturnCode l_rc; - constraints l_const(i_stop, i_speed, end_boundary::STOP_AFTER_ADDRESS, i_address); - continuous_scrub_operation l_op(i_target, l_const, l_rc); - - FAPI_ASSERT( l_rc == FAPI2_RC_SUCCESS, - fapi2::MSS_MEMDIAGS_CONTINUOUS_SCRUB_FAILED_TO_INIT().set_MCBIST_TARGET(i_target), - "Unable to initialize the MCBIST engine for a continuous scrub %s", mss::c_str(i_target) ); - - return l_op.execute(); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Scrub - targeted scrub all memory behind the target -/// @param[in] i_target the target behind which all memory should be scrubbed -/// @param[in] i_stop stop conditions -/// @param[in] i_start_address mcbist::address representing the address from which to start. -/// @param[in] i_end_address mcbist::address representing the address at which to end. -/// @param[in] i_end whether to end, and where (defaults to not stop on error) -/// @return FAPI2_RC_SUCCESS iff everything ok -/// @note The function is asynchronous, and the caller should be looking for a done attention -/// @note The caller can use the address range functions to calculate the end address as needed -/// -template<> -fapi2::ReturnCode targeted_scrub( const fapi2::Target& i_target, - const stop_conditions& i_stop, - const mss::mcbist::address& i_start_address, - const mss::mcbist::address& i_end_address, - const end_boundary i_end ) -{ - FAPI_INF("targeted scrub for %s", mss::c_str(i_target)); - - fapi2::ReturnCode l_rc; - constraints l_const(i_stop, speed::LUDICROUS, i_end, i_start_address, i_end_address); - targeted_scrub_operation l_op(i_target, l_const, l_rc); - - FAPI_ASSERT( l_rc == FAPI2_RC_SUCCESS, - fapi2::MSS_MEMDIAGS_TARGETED_SCRUB_FAILED_TO_INIT().set_MCBIST_TARGET(i_target), - "Unable to initialize the MCBIST engine for a targeted scrub %s", mss::c_str(i_target) ); - - return l_op.execute(); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Continue current command on next address -/// The current commaand has paused on an error, so we can record the address of the error -/// and finish the current master or slave rank. -/// @param[in] i_target the target -/// @param[in] i_end whether to end, and where (default = don't stop at end of rank) -/// @param[in] i_stop stop conditions (default - 0 meaning 'don't change conditions') -/// @param[in] i_speed the speed to scrub (default - SAME_SPEED meaning leave speed untouched) -/// @return FAPI2_RC_SUCCESS iff ok -/// @note overloaded as there's no 'invalid' state for thresholds. -/// -template<> -fapi2::ReturnCode continue_cmd( const fapi2::Target& i_target, - const end_boundary i_end, - const stop_conditions& i_stop, - const speed i_speed ) -{ - // Too long, make shorter - using TT = mss::mcbistTraits; - // We can use a local mcbist::program to help with the bit processing, and then write just the registers we touch. - mss::mcbist::program l_program; - fapi2::buffer l_status; +} // namespace memdiags - FAPI_INF("continue_cmd for %s", mss::c_str(i_target)); - - // TODO RTC:155518 Check for stop or in progress before allowing continue. Not critical - // as the caller should know and can check the in-progress bit in the event they don't - - if (i_end != end_boundary::DONT_CHANGE) - { - // Before we go too far, check to see if we're already stopped at the boundary we are asking to stop at - bool l_stopped_at_boundary = false; - uint64_t l_error_mode = 0; - bool l_detect_slave = false; - - FAPI_TRY( mss::getScom(i_target, TT::CFGQ_REG, l_program.iv_config) ); - FAPI_TRY( mss::getScom(i_target, TT::MCBAGRAQ_REG, l_program.iv_addr_gen) ); - l_program.iv_config.extractToRight(l_error_mode); - l_detect_slave = l_program.iv_addr_gen.getBit(); - - switch (i_end) - { - case end_boundary::STOP_AFTER_ADDRESS: - l_stopped_at_boundary = - l_program.iv_config.getBit() || - l_error_mode == end_boundary::STOP_AFTER_ADDRESS; - break; - - case end_boundary::STOP_AFTER_SLAVE_RANK: - // Note: we really want STOP_AFTER_MASTER_RANK here even though we're in the slave - // case because MASTER_RANK has the a 0 so that l_error_mode will check correctly - l_stopped_at_boundary = - l_program.iv_config.getBit() || - ((l_error_mode == end_boundary::STOP_AFTER_MASTER_RANK) && (l_detect_slave == false)); - break; - - case end_boundary::STOP_AFTER_MASTER_RANK: - l_stopped_at_boundary = - l_program.iv_config.getBit() || - ((l_error_mode == end_boundary::STOP_AFTER_MASTER_RANK) && (l_detect_slave == true)); - break; - - case end_boundary::STOP_AFTER_SUBTEST: - l_stopped_at_boundary = - l_program.iv_config.getBit() || - l_error_mode == end_boundary::STOP_AFTER_SUBTEST; - break; - - // By default we're not stopped at a boundary we're going to continue from - default: - break; - }; - - FAPI_ASSERT( l_stopped_at_boundary == false, - fapi2::MSS_MEMDIAGS_ALREADY_AT_BOUNDARY().set_MCBIST_TARGET(i_target).set_BOUNDARY(i_stop), - "Asked to stop at a boundary, but we're already there" ); - - // Ok, if we're here either we need to change the stop and boundary conditions. - // Read-modify-write the fields in the program. - FAPI_TRY( mss::getScom(i_target, TT::MCBAGRAQ_REG, l_program.iv_addr_gen) ); - - // Configure broadcast mode if needed - FAPI_TRY(mss::mcbist::configure_broadcast_mode(i_target, l_program)); - - l_program.change_end_boundary(i_end); - - FAPI_TRY( mss::mcbist::load_addr_gen(i_target, l_program) ); - - FAPI_TRY( mss::mcbist::load_config(i_target, l_program) ); - } - - // Thresholds - // According to API definition, 0 means don't change conditions - if( i_stop != stop_conditions::DONT_CHANGE) - { - FAPI_TRY( mss::mcbist::load_thresholds(i_target, i_stop) ); - } - - // Setup speed - FAPI_TRY( l_program.change_speed(i_target, i_speed) ); - - // Load new speed unless we aren't changing it - if( i_speed != speed::SAME_SPEED ) - { - FAPI_TRY( load_mcbparm(i_target, l_program) ); - } - - // Tickle the resume from pause - FAPI_TRY( mss::mcbist::resume(i_target) ); - -fapi_try_exit: - return fapi2::current_err; -} - -} - -} +} // namespace mss -- cgit v1.2.1