diff options
author | Zane Shelley <zshelle@us.ibm.com> | 2016-11-09 15:52:48 -0600 |
---|---|---|
committer | Zane C. Shelley <zshelle@us.ibm.com> | 2016-12-06 10:00:39 -0500 |
commit | 1613ef4b00c0a8fcf6b171cf51fc8ee61e9f356f (patch) | |
tree | b49ec2bb214bf584e66be95b0d28c625e7e4fd30 /src/usr/diag/prdf/plat | |
parent | f8578ea4bc4244b999d5114bc752c24306a19586 (diff) | |
download | talos-hostboot-1613ef4b00c0a8fcf6b171cf51fc8ee61e9f356f.tar.gz talos-hostboot-1613ef4b00c0a8fcf6b171cf51fc8ee61e9f356f.zip |
PRD: Determine where to restart commands after cmd complete attn
Change-Id: Ibd39b252c3cb00946c061a2f8090af7a7de3e3f2
RTC: 157892
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/32452
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Reviewed-by: Caleb N. Palmer <cnpalmer@us.ibm.com>
Reviewed-by: Benjamin J. Weisenbeck <bweisenb@us.ibm.com>
Reviewed-by: Zane C. Shelley <zshelle@us.ibm.com>
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/33076
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Diffstat (limited to 'src/usr/diag/prdf/plat')
-rw-r--r-- | src/usr/diag/prdf/plat/mem/prdfMemTdCtlr.C | 122 | ||||
-rw-r--r-- | src/usr/diag/prdf/plat/mem/prdfMemTdCtlr.H | 28 | ||||
-rw-r--r-- | src/usr/diag/prdf/plat/mem/prdfMemTdCtlr_ipl.C | 58 | ||||
-rw-r--r-- | src/usr/diag/prdf/plat/mem/prdfMemTdCtlr_rt.C | 25 | ||||
-rw-r--r-- | src/usr/diag/prdf/plat/mem/prdfMemTdRankList.H | 198 | ||||
-rw-r--r-- | src/usr/diag/prdf/plat/mem/prdfP9Mcbist.C | 38 | ||||
-rw-r--r-- | src/usr/diag/prdf/plat/mem/prdfP9McbistDataBundle.H | 10 | ||||
-rw-r--r-- | src/usr/diag/prdf/plat/mem/prdf_plat_mem_hb_only.mk | 1 | ||||
-rw-r--r-- | src/usr/diag/prdf/plat/prdfPlatServices.C | 11 |
9 files changed, 447 insertions, 44 deletions
diff --git a/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr.C b/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr.C new file mode 100644 index 000000000..5f7138271 --- /dev/null +++ b/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr.C @@ -0,0 +1,122 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/diag/prdf/plat/mem/prdfMemTdCtlr.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2016 */ +/* [+] 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. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ + +#include <prdfMemTdCtlr.H> + +#include <prdfMemAddress.H> +#include <prdfP9McbistDataBundle.H> + +using namespace TARGETING; + +namespace PRDF +{ + +using namespace PlatServices; + +//------------------------------------------------------------------------------ + +template<> +uint32_t MemTdCtlr<TYPE_MCBIST, McbistDataBundle *>::initStoppedRank() +{ + #define PRDF_FUNC "[initStoppedRank] " + + uint32_t o_rc = SUCCESS; + + do + { + // Get all ports in which the command was run. In broadcast mode, the + // rank configuration for all ports will be the same. In non-broadcast + // mode, there will only be one MCA in the list. Therefore, we can + // simply use the first MCA in the list for all configs. + std::vector<ExtensibleChip *> portList; + o_rc = getMcbistMaintPort( iv_chip, portList ); + if ( SUCCESS != o_rc ) + { + PRDF_ERR( PRDF_FUNC "getMcbistMaintPort(0x%08x) failed", + iv_chip->getHuid() ); + break; + } + + // Get the rank in which the command stopped. + MemAddr addr; + o_rc = getMemMaintAddr<TYPE_MCBIST>( iv_chip, addr ); + if ( SUCCESS != o_rc ) + { + PRDF_ERR( PRDF_FUNC "getMemMaintAddr<TYPE_MCBIST>(0x%08x) failed", + iv_chip->getHuid() ); + break; + } + + // Update iv_stoppedRank. + iv_stoppedRank = TdRankListEntry ( portList.front(), addr.getRank() ); + #ifndef __HOSTBOOT_RUNTIME + // Update iv_broadcastMode. + iv_broadcastMode = ( 1 < portList.size() ); + #endif + + } while (0); + + return o_rc; + + #undef PRDF_FUNC +} + +//------------------------------------------------------------------------------ + +/* RTC 136128 +template<> +uint32_t MemTdCtlr<TYPE_MBA, MbaDataBundle *>::initStoppedRank() +{ + #define PRDF_FUNC "[initStoppedRank] " + + uint32_t o_rc = SUCCESS; + + do + { + // Get the rank in which the command stopped. + MemAddr addr; + o_rc = getMemMaintAddr<TYPE_MBA>( iv_chip, addr ); + if ( SUCCESS != o_rc ) + { + PRDF_ERR( PRDF_FUNC "getMemMaintAddr<TYPE_MBA>(0x%08x) failed", + iv_chip->getHuid() ); + break; + } + + // Update iv_stoppedRank. + iv_stoppedRank = TdRankListEntry( iv_chip, addr.getRank() ); + + } while (0); + + return o_rc; + + #undef PRDF_FUNC +} +*/ + +//------------------------------------------------------------------------------ + +} // end namespace PRDF + diff --git a/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr.H b/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr.H index c2f409ef0..efc6d4bcd 100644 --- a/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr.H +++ b/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr.H @@ -35,6 +35,7 @@ // Platform includes #include <prdfMemTdQueue.H> +#include <prdfMemTdRankList.H> #include <prdfPlatServices.H> namespace PRDF @@ -57,7 +58,7 @@ class MemTdCtlr * @param i_chip An MCBIST or MBA chip. */ explicit MemTdCtlr( ExtensibleChip * i_chip ) : - iv_chip( i_chip ) + iv_chip( i_chip ), iv_rankList( i_chip ) { PRDF_ASSERT( T == iv_chip->getType() ); } @@ -162,6 +163,15 @@ class MemTdCtlr return rc; } + /** + * @brief This is called when handling a command complete attention for a + * non-TD command to initialize iv_stoppedRank and iv_broadcastMode, + * which are used to indicate where the command should resume after + * targeted diagnostics is compete. + * @return Non-SUCCESS if an internal function fails, SUCCESS otherwise. + */ + uint32_t initStoppedRank(); + #ifdef __HOSTBOOT_RUNTIME /** @@ -193,11 +203,27 @@ class MemTdCtlr /** The procedure that is currently in progress. */ TdEntry * iv_curProcedure = nullptr; + /** A list of all ranks behind iv_chip. */ + TdRankList<T> iv_rankList; + + /** If a non-TD command stopped somewhere in the middle of memory, PRD will + * need to restart that command on the next configured rank. This variable + * stores where the non-TD command stopped. The non-command will then be + * restarted on the next rank in defaultStep() after all targeted + * diagnostics are complete. */ + TdRankListEntry iv_stoppedRank; + #ifdef __HOSTBOOT_RUNTIME /** True if the TD controller has been initialized. False otherwise. */ bool iv_initialized = false; + #else // IPL only + + /** Combined with iv_stoppedRank. Indicates if the non-TD command that + * stopped was in broadcast mode or not. */ + bool iv_broadcastMode = false; + #endif }; diff --git a/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr_ipl.C b/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr_ipl.C index 0c1bc6d22..3f2c7f09e 100644 --- a/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr_ipl.C +++ b/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr_ipl.C @@ -30,6 +30,7 @@ #include <prdfMemTdCtlr.H> // Platform includes +#include <prdfMemScrubUtils.H> #include <prdfP9McbistDataBundle.H> #include <prdfP9McbistExtraSig.H> @@ -72,6 +73,14 @@ uint32_t MemTdCtlr<T,D>::handleCmdComplete( STEP_CODE_DATA_STRUCT & io_sc ) // queue to handle the errors and finish the pattern test to the end // of memory). + // Keep track of where the command stopped. + o_rc = initStoppedRank(); + if ( SUCCESS != o_rc ) + { + PRDF_ERR( PRDF_FUNC "initStoppedRank() failed" ); + break; + } + // TODO: RTC 157892 Check why the command stopped and take actions // appropriately. Note that since nothing is happening here at // the moment, the code will simply assume the command stopped @@ -128,11 +137,49 @@ uint32_t MemTdCtlr<T,D>::defaultStep( STEP_CODE_DATA_STRUCT & io_sc ) uint32_t o_rc = SUCCESS; - // The command complete message to MDIA must be sent after clearing the - // attention. Otherwise, we may run into a race condition where MDIA may try - // to start the next command before PRD clears the FIR bits. - D db = static_cast<D>(iv_chip->getDataBundle()); - db->iv_sendCmdCompleteMsg = true; + TdRankListEntry nextRank = iv_rankList.getNext( iv_stoppedRank, + iv_broadcastMode ); + + do + { + if ( nextRank <= iv_stoppedRank ) // The command made it to the end. + { + // Clear all of the counters and maintenance ECC attentions. This + // must be done before telling MDIA the command is done. Otherwise, + // we may run into a race condition where MDIA may start the next + // command and it completes before PRD clears the FIR bits for this + // attention. + o_rc = prepareNextCmd<T>( iv_chip ); + if ( SUCCESS != o_rc ) + { + PRDF_ERR( PRDF_FUNC "prepareNextCmd<T>(0x%08x) failed", + iv_chip->getHuid() ); + break; + } + + // The command reached the end of memory. Send a message to MDIA. + o_rc = mdiaSendEventMsg(iv_chip->getTrgt(), MDIA::COMMAND_COMPLETE); + if ( SUCCESS != o_rc ) + { + PRDF_ERR( PRDF_FUNC "mdiaSendEventMsg(0x%08x,COMMAND_COMPLETE) " + "failed", iv_chip->getHuid() ); + break; + } + } + else // There is memory left to test. + { + // Start a super fast command to the end of memory. + o_rc = startSfRead<T>( nextRank.getChip(), nextRank.getRank() ); + if ( SUCCESS != o_rc ) + { + PRDF_ERR( PRDF_FUNC "startSfRead<T>(0x%08x,%d) failed", + nextRank.getChip()->getHuid(), + nextRank.getRank().getMaster() ); + break; + } + } + + } while (0); return o_rc; @@ -148,4 +195,3 @@ template class MemTdCtlr<TYPE_MCBIST, McbistDataBundle *>; } // end namespace PRDF - diff --git a/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr_rt.C b/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr_rt.C index ec5b48c8b..6e592c18a 100644 --- a/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr_rt.C +++ b/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr_rt.C @@ -41,6 +41,8 @@ using namespace TARGETING; namespace PRDF { +using namespace PlatServices; + template <TYPE T, typename D> uint32_t MemTdCtlr<T,D>::handleCmdComplete( STEP_CODE_DATA_STRUCT & io_sc ) { @@ -64,6 +66,14 @@ uint32_t MemTdCtlr<T,D>::handleCmdComplete( STEP_CODE_DATA_STRUCT & io_sc ) // procedures to the queue and move on to the next step in the state // machine. + // Keep track of where the command stopped. + o_rc = initStoppedRank(); + if ( SUCCESS != o_rc ) + { + PRDF_ERR( PRDF_FUNC "initStoppedRank() failed" ); + break; + } + // TODO: RTC 136126 Note that since nothing is happening here at // the moment, the code will simply assume the command stopped // without error and background scrubbing will resume. @@ -133,7 +143,7 @@ uint32_t MemTdCtlr<T,D>::handleTdEvent( STEP_CODE_DATA_STRUCT & io_sc, if ( nullptr != iv_curProcedure ) break; // Stop background scrubbing. - o_rc = PlatServices::stopBgScrub<T>( iv_chip ); + o_rc = stopBgScrub<T>( iv_chip ); if ( SUCCESS != o_rc ) { PRDF_ERR( PRDF_FUNC "stopBgScrub<T>(0x%08x) failed", @@ -192,10 +202,19 @@ uint32_t MemTdCtlr<T,D>::defaultStep( STEP_CODE_DATA_STRUCT & io_sc ) uint32_t o_rc = SUCCESS; + TdRankListEntry nextRank = iv_rankList.getNext( iv_stoppedRank ); + do { - // Restart background scrubbing. - // TODO: RTC 136126 + // Restart background scrubbing on the next rank. + o_rc = startBgScrub<T>( nextRank.getChip(), nextRank.getRank() ); + if ( SUCCESS != o_rc ) + { + PRDF_ERR( PRDF_FUNC "startBgScrub<T>(0x%08x,%d) failed", + nextRank.getChip()->getHuid(), + nextRank.getRank().getMaster() ); + break; + } } while (0); diff --git a/src/usr/diag/prdf/plat/mem/prdfMemTdRankList.H b/src/usr/diag/prdf/plat/mem/prdfMemTdRankList.H new file mode 100644 index 000000000..c6c85a874 --- /dev/null +++ b/src/usr/diag/prdf/plat/mem/prdfMemTdRankList.H @@ -0,0 +1,198 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/diag/prdf/plat/mem/prdfMemTdRankList.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2013,2016 */ +/* [+] 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. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ + +#ifndef __prdfTdRankList_H +#define __prdfTdRankList_H + +// Platform includes +#include <prdfMemRank.H> +#include <prdfPlatServices.H> + +// Other includes +#include <algorithm> +#include <vector> + +namespace PRDF +{ + +/** @brief Structure to represent a rank list entry. */ +class TdRankListEntry +{ + public: + + /** @brief Default constructor. */ + TdRankListEntry() = default; + + /** @brief Constructor from components. */ + TdRankListEntry( ExtensibleChip * i_chip, const MemRank & i_rank ) : + iv_chip(i_chip), iv_rank(i_rank) + {} + + /** @brief Accessor function. */ + ExtensibleChip * getChip() const { return iv_chip; } + + /** @brief Accessor function. */ + MemRank getRank() const { return iv_rank; } + + /** @brief '==' operator */ + bool operator==( const TdRankListEntry & e ) const + { + PRDF_ASSERT( this->getChip()->getType() == e.getChip()->getType() ); + return ( this->getChip()->getPos() == e.getChip()->getPos() ) && + ( this->iv_rank == e.iv_rank ); + } + + /** @brief '<' operator */ + bool operator<( const TdRankListEntry & e ) const + { + PRDF_ASSERT( this->getChip()->getType() == e.getChip()->getType() ); + return ( this->getChip()->getPos() < e.getChip()->getPos() ) || + ( (this->getChip()->getPos() == e.getChip()->getPos()) && + (this->getRank() < e.getRank() ) ); + } + + /** @brief '<=' operator */ + bool operator<=( const TdRankListEntry & e ) const + { + return ( *this < e || *this == e ); + } + + private: + + ExtensibleChip * iv_chip; ///< MCA or MBA chip. + MemRank iv_rank; ///< Any rank on the MCA or MBA. +}; + +/** + * @brief A sorted list of all master/slave ranks behind an MBA or MCBIST. The + * list will be sorted by the order in which hardware will scrub memory. + */ +template <TARGETING::TYPE T> +class TdRankList +{ + public: // structs, typedefs + + public: // functions + + /** + * @brief Constructor. + * @param MCBIST or MBA chip. + */ + explicit TdRankList( ExtensibleChip * i_chip ); + + /** + * @brief Will return the entry in the list that immediately follows the + * given entry. + * + * If the current entry is at the end of the list, this function will wrap + * around to the beginning of the list. In broadcast mode, the rank + * configuration for all chips will be the same. Therefore, this function + * will wrap to the first rank for the given chip, if needed. Users can + * compare if the 'next' entry is less than or equal to the 'current' entry + * to determine of the search wrapped. + * + * @param i_current The staring point for the search. + * @param i_broadcastMode True if commands are being run in broadcast mode + * (MCBIST super-fast commands only). False + * otherwise. + * @return The next entry in the list. + */ + TdRankListEntry getNext( const TdRankListEntry & i_current, + bool i_broadcastMode = false ) const + { + // Find the current entry in the list. + std::vector<TdRankListEntry>::const_iterator next_it; + next_it = std::find( iv_list.begin(), iv_list.end(), i_current ); + PRDF_ASSERT( iv_list.end() != next_it ); // code bug + + // Get the next entry and wrap to the beginning, if needed. + if ( iv_list.end() == ++next_it ) next_it = iv_list.begin(); + + // Check broadcast mode. If the chip changed, wrap to the first rank of + // the given chip. This is to ensure the user can do the 'next <= + // current' check to determine if it wrapped. + if ( i_broadcastMode && (i_current.getChip() != next_it->getChip()) ) + { + // The rank configurations for all chips will be the same. Also, we + // know the rank in the next entry will be the first rank of that + // chip. So we can assume the rank in the next entry will be the + // first rank of the target chip. + TdRankListEntry entry ( i_current.getChip(), next_it->getRank() ); + next_it = std::find( iv_list.begin(), iv_list.end(), entry ); + PRDF_ASSERT( iv_list.end() != next_it ); // code bug + } + + return *next_it; + } + + private: // instance variables + + std::vector<TdRankListEntry> iv_list; ///< The list of ranks. +}; + +//------------------------------------------------------------------------------ + +template<> +inline TdRankList<TARGETING::TYPE_MCBIST>::TdRankList( ExtensibleChip * i_chip ) +{ + using namespace TARGETING; + using namespace PlatServices; + + PRDF_ASSERT( TYPE_MCBIST == i_chip->getType() ); + + ExtensibleChipList mcaChipList = getConnected( i_chip, TYPE_MCA ); + for ( auto & mcaChip : mcaChipList ) + { + std::vector<MemRank> rankList; + getSlaveRanks<TYPE_MCA>( mcaChip->getTrgt(), rankList ); + for ( auto & rank : rankList ) + { + iv_list.push_back( TdRankListEntry(mcaChip, rank) ); + } + } +} + +//------------------------------------------------------------------------------ + +template<> +inline TdRankList<TARGETING::TYPE_MBA>::TdRankList( ExtensibleChip * i_chip ) +{ + using namespace TARGETING; + using namespace PlatServices; + + PRDF_ASSERT( TYPE_MBA == i_chip->getType() ); + + std::vector<MemRank> rankList; + getSlaveRanks<TYPE_MBA>( i_chip->getTrgt(), rankList ); + for ( auto & rank : rankList ) + { + iv_list.push_back( TdRankListEntry(i_chip, rank) ); + } +} + +} // end namespace PRDF + +#endif // __prdfTdRankList_H + diff --git a/src/usr/diag/prdf/plat/mem/prdfP9Mcbist.C b/src/usr/diag/prdf/plat/mem/prdfP9Mcbist.C index 47349feab..2d43025d3 100644 --- a/src/usr/diag/prdf/plat/mem/prdfP9Mcbist.C +++ b/src/usr/diag/prdf/plat/mem/prdfP9Mcbist.C @@ -78,27 +78,6 @@ int32_t PostAnalysis( ExtensibleChip * i_mcbChip, { #define PRDF_FUNC "[p9_mcbist::PostAnalysis] " - #ifndef __HOSTBOOT_RUNTIME - - // Send command complete to MDIA. - // This must be done in post analysis after attentions have been cleared. - - McbistDataBundle * mcbdb = getMcbistDataBundle( i_mcbChip ); - - if ( mcbdb->iv_sendCmdCompleteMsg ) - { - mcbdb->iv_sendCmdCompleteMsg = false; - - int32_t rc = mdiaSendEventMsg( i_mcbChip->getTrgt(), - MDIA::COMMAND_COMPLETE ); - if ( SUCCESS != rc ) - { - PRDF_ERR( PRDF_FUNC "mdiaSendEventMsg(COMMAND_COMPLETE) failed" ); - } - } - - #endif // not __HOSTBOOT_RUNTIME - return SUCCESS; // Always return SUCCESS for this plugin. #undef PRDF_FUNC @@ -123,9 +102,20 @@ int32_t McbistCmdComplete( ExtensibleChip * i_mcbChip, #define PRDF_FUNC "[p9_mcbist::McbistCmdComplete] " // Tell the TD controller there was a command complete attention. - getMcbistDataBundle(i_mcbChip)->getTdCtlr()->handleCmdComplete( io_sc ); - - return SUCCESS; // Always return SUCCESS for this plugin. + McbistDataBundle * db = getMcbistDataBundle( i_mcbChip ); + if ( SUCCESS != db->getTdCtlr()->handleCmdComplete(io_sc) ) + { + // Something failed. It is possible the command complete attention has + // not been cleared. Make the rule code do it. + return SUCCESS; + } + else + { + // Everything was successful. Whether we started a new command or told + // MDIA to do it, the command complete bit has already been cleared. + // Don't do it again. + return PRD_NO_CLEAR_FIR_BITS; + } #undef PRDF_FUNC } diff --git a/src/usr/diag/prdf/plat/mem/prdfP9McbistDataBundle.H b/src/usr/diag/prdf/plat/mem/prdfP9McbistDataBundle.H index 4c55a8ee7..86daecef8 100644 --- a/src/usr/diag/prdf/plat/mem/prdfP9McbistDataBundle.H +++ b/src/usr/diag/prdf/plat/mem/prdfP9McbistDataBundle.H @@ -76,16 +76,6 @@ class McbistDataBundle : public DataBundle return iv_tdCtlr; } - public: // instance variables - - #ifndef __HOSTBOOT_RUNTIME - - /** TRUE if a message needs to be sent to MDIA in the post analysis plugin, - * FALSE otherwise. */ - bool iv_sendCmdCompleteMsg = false; - - #endif - private: // instance variables /** The MCBIST chip associated with this data bundle. */ diff --git a/src/usr/diag/prdf/plat/mem/prdf_plat_mem_hb_only.mk b/src/usr/diag/prdf/plat/mem/prdf_plat_mem_hb_only.mk index 89198b76f..96f050e5e 100644 --- a/src/usr/diag/prdf/plat/mem/prdf_plat_mem_hb_only.mk +++ b/src/usr/diag/prdf/plat/mem/prdf_plat_mem_hb_only.mk @@ -40,6 +40,7 @@ prd_incpath += ${PRD_SRC_PATH}/plat/mem # plat/mem/ (non-rule plugin related) prd_obj += prdfMemMark.o prd_obj += prdfMemScrubUtils.o +prd_obj += prdfMemTdCtlr.o # plat/mem/ (rule plugin related) prd_rule_plugin += prdfP9Mca.o diff --git a/src/usr/diag/prdf/plat/prdfPlatServices.C b/src/usr/diag/prdf/plat/prdfPlatServices.C index b2ad6ffb1..3c52b3a0b 100644 --- a/src/usr/diag/prdf/plat/prdfPlatServices.C +++ b/src/usr/diag/prdf/plat/prdfPlatServices.C @@ -370,6 +370,17 @@ uint32_t startBgScrub<TYPE_MCA>( ExtensibleChip * i_mcaChip, #undef PRDF_FUNC } +//------------------------------------------------------------------------------ + +// This specialization only exists to avoid a lot of extra code in some classes. +// The input chip must still be an MCA chip. +template<> +uint32_t startBgScrub<TYPE_MCBIST>( ExtensibleChip * i_mcaChip, + const MemRank & i_rank ) +{ + return startBgScrub<TYPE_MCA>( i_mcaChip, i_rank ); +} + //############################################################################## //## Centaur Maintenance Command wrappers //############################################################################## |