diff options
author | Zane Shelley <zshelle@us.ibm.com> | 2016-07-08 15:37:12 -0500 |
---|---|---|
committer | Daniel M. Crowell <dcrowell@us.ibm.com> | 2016-07-26 17:45:34 -0400 |
commit | a264b75d64d6b6e34f4502190504362e831744a1 (patch) | |
tree | 6199e29dd21fc4b51af027c6e640e50852ceb2f9 /src/usr/diag/prdf/plat/mem/prdfMemTdQueue.H | |
parent | 1e47d3c4acd5732a8f1abc8b19e7be0dea294635 (diff) | |
download | talos-hostboot-a264b75d64d6b6e34f4502190504362e831744a1.tar.gz talos-hostboot-a264b75d64d6b6e34f4502190504362e831744a1.zip |
PRD: Created Targeted Diagnostics queue for P9
Change-Id: I24c145a483b8182e2dce296e74908035c42770c9
RTC: 157466
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/26936
Reviewed-by: Caleb N. Palmer <cnpalmer@us.ibm.com>
Tested-by: Jenkins Server <pfd-jenkins+hostboot@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/27393
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/usr/diag/prdf/plat/mem/prdfMemTdQueue.H')
-rwxr-xr-x | src/usr/diag/prdf/plat/mem/prdfMemTdQueue.H | 294 |
1 files changed, 294 insertions, 0 deletions
diff --git a/src/usr/diag/prdf/plat/mem/prdfMemTdQueue.H b/src/usr/diag/prdf/plat/mem/prdfMemTdQueue.H new file mode 100755 index 000000000..d74e45736 --- /dev/null +++ b/src/usr/diag/prdf/plat/mem/prdfMemTdQueue.H @@ -0,0 +1,294 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/diag/prdf/plat/mem/prdfMemTdQueue.H $ */ +/* */ +/* 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 */ + +/** @file prdfMemTdQueue.H + * @brief Support code for a Targeted Diagnostics weighted event queue. + */ + +#ifndef __prdfMemTdQueue_H +#define __prdfMemTdQueue_H + +// Framework includes +#include <iipServiceDataCollector.h> + +// Platform includes +#include <prdfMemRank.H> + +// Other includes +#include <algorithm> +#include <vector> + +namespace PRDF +{ + +//------------------------------------------------------------------------------ +// TdEntry classes +//------------------------------------------------------------------------------ + +/** @brief Abstract class for a Targeted Diagnostics event. */ +class TdEntryBase +{ + public: // enums, constants + + /** + * @brief This enum will be used to indicate type of TD event requested to + * be handled. + * @note The order of the enums values is important because it is used for + * sorting the TdQueue by event type priority. + */ + enum TdType + { + VCM_EVENT = 0, ///< A Verify Chip Mark event. + TPS_EVENT, ///< A Two-Phase Scrub event. + }; + + public: // functions + + /** @brief Default destructor */ + virtual ~TdEntryBase() = default; + + /** + * @brief Each entry will have a set of steps that need to be performed. + * This function tells the procedure to move onto the next step. + * @param io_sc The step code data struct. + * @param o_done Returns true if this procedure is complete, false + * otherwise. + * @return Non-SUCCESS if an internal function fails, SUCCESS otherwise. + */ + virtual uint32_t nextStep( STEP_CODE_DATA_STRUCT & io_sc, + bool & o_done ) = 0; + + protected: // functions + + /** @brief Constructor */ + TdEntryBase( TdType i_tdType, ExtensibleChip * i_chip, MemRank i_rank ) : + iv_tdType(i_tdType), iv_rank(i_rank), iv_chip(i_chip) + {} + + protected: // instance variables + + const TdType iv_tdType; ///< The event type (see enum TdType). + const MemRank iv_rank; ///< The rank in which this event occurred. + + /** The chip associated with this entry. This isn't used for any + * comparisons, but is needed for every TD procedure. */ + ExtensibleChip * const iv_chip; +}; + +// Only implement specializations of TdEntry. +template<TARGETING::TYPE T> class TdEntry; + +/** @brief TdEntry specialization for MCBIST. */ +template<> +class TdEntry<TARGETING::TYPE_MCBIST> : public TdEntryBase +{ + public: // enums, constants + + enum + { + PORTS_PER_MCBIST = 4, + }; + + public: // functions + + /** @brief Default destructor */ + virtual ~TdEntry<TARGETING::TYPE_MCBIST>() = default; + + // Overloaded functions + virtual uint32_t nextStep( STEP_CODE_DATA_STRUCT & io_sc, + bool & o_done ) = 0; + + /** @brief '==' operator */ + bool operator==( const TdEntry<TARGETING::TYPE_MCBIST> & i_e ) const + { + return ( this->iv_tdType == i_e.iv_tdType && + this->iv_rank == i_e.iv_rank && + this->iv_port == i_e.iv_port ); + } + + /** + * @brief '<' operator + * @note This only compares iv_tdType because the TdQueue only sorts by type + */ + bool operator<( const TdEntry<TARGETING::TYPE_MCBIST> & i_e ) const + { + return this->iv_tdType < i_e.iv_tdType; + } + + protected: // functions + + /** @brief Constructor */ + TdEntry<TARGETING::TYPE_MCBIST>( TdType i_tdType, ExtensibleChip * i_chip, + MemRank i_rank, uint8_t i_port ) : + TdEntryBase(i_tdType, i_chip, i_rank), iv_port(i_port) + { + PRDF_ASSERT( TARGETING::TYPE_MCBIST == iv_chip->getTrgtType() ); + PRDF_ASSERT( iv_port < PORTS_PER_MCBIST ); + } + + protected: // Instance variables + + const uint32_t iv_port; ///< MCBIST memory port. +}; + +/** @brief TdEntry specialization for MBA. */ +template<> +class TdEntry<TARGETING::TYPE_MBA> : public TdEntryBase +{ + public: // functions + + /** @brief Default destructor */ + virtual ~TdEntry<TARGETING::TYPE_MBA>() = default; + + // Overloaded functions + virtual uint32_t nextStep( STEP_CODE_DATA_STRUCT & io_sc, + bool & o_done ) = 0; + + /** @brief '==' operator */ + bool operator==( const TdEntry<TARGETING::TYPE_MBA> & i_e ) const + { + return ( this->iv_tdType == i_e.iv_tdType && + this->iv_rank == i_e.iv_rank ); + } + + /** + * @brief '<' operator + * @note This only compares iv_tdType because the TdQueue only sorts by type + */ + bool operator<( const TdEntry<TARGETING::TYPE_MBA> & i_e ) const + { + return this->iv_tdType < i_e.iv_tdType; + } + + protected: // functions + + /** @brief Constructor */ + TdEntry<TARGETING::TYPE_MBA>( TdType i_tdType, ExtensibleChip * i_chip, + MemRank i_rank ) : + TdEntryBase(i_tdType, i_chip, i_rank) + { + PRDF_ASSERT( TARGETING::TYPE_MBA == iv_chip->getTrgtType() ); + } +}; + +//------------------------------------------------------------------------------ +// TdQueue class +//------------------------------------------------------------------------------ + +/** + * @brief This is a weighted queue for all Targeted Diagnostics events. + * @note Events with a higher priority will be moved ahead of lower priority + * events. + */ +template <TARGETING::TYPE T> +class TdQueue +{ + public: // typedefs + + typedef std::vector< TdEntry<T> * > Queue; + typedef typename std::vector< TdEntry<T> * >::iterator QueueItr; + + public: // functions + + /** @brief Destructor. */ + ~TdQueue() { for ( auto & a : iv_queue ) delete a; } + + /** @return TRUE if the queue is empty, FALSE otherwise. */ + bool empty() const { return iv_queue.empty(); } + + /** + * @brief Sorts the queue by priority order then returns the first entry. + * @return The first entry in the queue. + * @note This is intended to be called only once for each time the TD + * controller needs to find the next TD procedure to do. If it is + * called multiple times, it is possible the list is reordered such + * that a new entry is moved to the front of the queue and is + * mistakenly removed via pop() before the TD controller is able to + * execute the request. + */ + TdEntry<T> * getNextEntry() + { + PRDF_ASSERT( !iv_queue.empty() ); + + // TODO: RTC 66487 This function currently has the complexity of + // O(n lg n) because of the sorting. It is possible to optimize + // this to O(n) if we use push_heap()/pop_heap(). However, there + // is a problem were push_heap() could possibly reorder the queue + // while a TD procedure is in progress, which is undesirable. + + std::sort( iv_queue.begin(), iv_queue.end(), + [](TdEntry<T> * a, TdEntry<T> * b) { return *a < *b; } ); + + return iv_queue.front(); + } + + /** + * @brief Add new TD entry at the end of the queue. + * @param i_e A TD entry. + * @note Only adds the entry to the queue if the entry does not already + * exist in the queue. + */ + void push( TdEntry<T> * i_e ) + { + QueueItr it = std::find_if( iv_queue.begin(), iv_queue.end(), + [=](TdEntry<T> * a){return *i_e == *a;} ); + if ( iv_queue.end() == it ) + { + iv_queue.push_back( i_e ); + } + } + + /** + * @brief Removes the entry at the beginning of the queue. + */ + // TODO: RTC 66487 This function currently has a complexity of 0(n). It + // is preferred to have 0(1), which could be accomplished with by + // using a deque or list. Unfortunately, Hostboot currently does not + // support std::deque or std::list::sort(). Therefore, we must use a + // vector at this time. + void pop() + { + PRDF_ASSERT( !iv_queue.empty() ); + + delete *(iv_queue.begin()); + iv_queue.erase(iv_queue.begin()); + } + + /** + * @return A constant reference to the queue. + * @note The only purpose for this is for FFDC. + */ + const Queue & getQueue() const { return iv_queue; } + + private: // instance variables + + /** Stores all ranks that are marked for targeted diagnostics. */ + Queue iv_queue; +}; + +} // end namespace PRDF + +#endif // __prdfMemTdQueue_H + |