summaryrefslogtreecommitdiffstats
path: root/src/usr/diag/prdf/plat/mem/prdfMemTdQueue.H
diff options
context:
space:
mode:
authorZane Shelley <zshelle@us.ibm.com>2016-07-08 15:37:12 -0500
committerDaniel M. Crowell <dcrowell@us.ibm.com>2016-07-26 17:45:34 -0400
commita264b75d64d6b6e34f4502190504362e831744a1 (patch)
tree6199e29dd21fc4b51af027c6e640e50852ceb2f9 /src/usr/diag/prdf/plat/mem/prdfMemTdQueue.H
parent1e47d3c4acd5732a8f1abc8b19e7be0dea294635 (diff)
downloadtalos-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-xsrc/usr/diag/prdf/plat/mem/prdfMemTdQueue.H294
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
+
OpenPOWER on IntegriCloud