diff options
author | Stephen Cprek <smcprek@us.ibm.com> | 2014-03-26 13:12:57 -0500 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2014-04-04 10:56:27 -0500 |
commit | 214b4da81b98c19c5dd8eb30b56b3b4d5d38e1c8 (patch) | |
tree | 5698b5251695fe1bc406610c3e3a2f8ed746085f /src | |
parent | 1be9762f6c1112555176ba474fe9a294c2ff1d95 (diff) | |
download | talos-hostboot-214b4da81b98c19c5dd8eb30b56b3b4d5d38e1c8.tar.gz talos-hostboot-214b4da81b98c19c5dd8eb30b56b3b4d5d38e1c8.zip |
Deconfigure targets by checking presence related targets
Centaurs behind a non-present processor are not being deconfigured
Change-Id: I2574d75d76d7b7c1f4a0089193a2f361b7ac7e13
RTC: 99406
CQ: SW253452
Backport: release-fips810
Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/9921
Tested-by: Jenkins Server
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/include/usr/hwas/common/deconfigGard.H | 6 | ||||
-rw-r--r-- | src/include/usr/hwas/common/hwas.H | 48 | ||||
-rw-r--r-- | src/include/usr/targeting/common/entitypath.H | 25 | ||||
-rw-r--r-- | src/include/usr/targeting/common/utilFilter.H | 21 | ||||
-rw-r--r-- | src/usr/hwas/common/deconfigGard.C | 6 | ||||
-rw-r--r-- | src/usr/hwas/common/hwas.C | 449 | ||||
-rw-r--r-- | src/usr/hwas/test/hwasGardTest.H | 309 | ||||
-rw-r--r-- | src/usr/targeting/common/entitypath.C | 31 | ||||
-rw-r--r-- | src/usr/targeting/common/utilFilter.C | 8 |
9 files changed, 742 insertions, 161 deletions
diff --git a/src/include/usr/hwas/common/deconfigGard.H b/src/include/usr/hwas/common/deconfigGard.H index 82519b6c1..52693a48a 100644 --- a/src/include/usr/hwas/common/deconfigGard.H +++ b/src/include/usr/hwas/common/deconfigGard.H @@ -134,6 +134,12 @@ public: // are found connected to a non-functional Centaur DECONFIGURED_BY_NO_PARENT_MEMBUF, // BASE | 0x09 + // set by presentByAssoc() when a MEMBUF has no DIMMs + DECONFIGURED_BY_NO_CHILD_DIMM, // BASE | 0x0A + + // set by presentByAssoc() when a MEMBUF has no MCS + DECONFIGURED_BY_NO_PARENT_MCS, // BASE | 0x0B + // mask - these bits mean it's a PLID and not an enum DECONFIGURED_BY_PLID_MASK = 0xFFFF0000, }; diff --git a/src/include/usr/hwas/common/hwas.H b/src/include/usr/hwas/common/hwas.H index 45418f568..3862ca9e7 100644 --- a/src/include/usr/hwas/common/hwas.H +++ b/src/include/usr/hwas/common/hwas.H @@ -40,6 +40,7 @@ /******************************************************************************/ #include <stdint.h> #include <targeting/common/commontargeting.H> +#include <hwas/common/deconfigGard.H> #include <hwas/common/hwasError.H> namespace HWAS @@ -124,6 +125,53 @@ errlHndl_t restrictEXunits( errlHndl_t checkMinimumHardware( const TARGETING::ConstTargetHandle_t i_node = NULL); +/** + * @brief Struct representing a particular target. Used by + * invokePresentByAssoc to populate a vector of TargetInfo's for subsequent + * use by deconfigPresentByAssoc + */ +struct TargetInfo +{ + TARGETING::ATTR_AFFINITY_PATH_type affinityPath; + TARGETING::Target * pThisTarget; + TARGETING::ATTR_HUID_type huid; + TARGETING::ATTR_TYPE_type type; + HWAS::DeconfigGard::DeconfiguredByReason reason; + bool functional; +}; + +// Structure populated in invokePresentByAssoc() for use in presentByAssoc() +typedef std::vector<TargetInfo> TargetInfoVector; + +/** + * @brief Invokes presentByAssoc + * + * Called by discoverTargets(). This function queries the system and populates + * a vector of structs representing functional MCS, MEMBUFS, DIMMS. + * This vector is then passed to presentByAssoc() which systematically adds + * targets to another vector to be deconfigured based on their related targets + * Upon completion of presentByAssoc(), this function iterates + * through the returned vector and deconfigures any targets marked + * for deconfiguration. + */ +void invokePresentByAssoc(); + +/** + * @brief Algorithm to check if a MCS has a MEMBUF, a MEMBUF has a MCS and DIMM, + * and a DIMM has a MEMBUF. + * + * The vector o_funcTargets is sorted by affinity path to allow a single pass + * with some backtracking to check every scenario more efficiently. + * These checks are needed because of scenarios where targets are non-present + * and their related targets are not marked as deconfigured + * + * @param[in/out] o_funcTargets A vector of functional MCS, MEMBUFS, DIMMS + * @param[in/out] o_targToDeconfig A vector of targets to deconfigure, done + * this way to allow unit tests + */ +void presentByAssoc(TargetInfoVector& o_funcTargets, + TargetInfoVector& o_targToDeconfig); + }; // end namespace #endif diff --git a/src/include/usr/targeting/common/entitypath.H b/src/include/usr/targeting/common/entitypath.H index cee5422cc..13fa86d39 100644 --- a/src/include/usr/targeting/common/entitypath.H +++ b/src/include/usr/targeting/common/entitypath.H @@ -5,7 +5,7 @@ /* */ /* IBM CONFIDENTIAL */ /* */ -/* COPYRIGHT International Business Machines Corp. 2011,2012 */ +/* COPYRIGHT International Business Machines Corp. 2011,2014 */ /* */ /* p1 */ /* */ @@ -255,6 +255,29 @@ class EntityPath const EntityPath& i_rhs) const; /** + * @brief Returns whether an entity path is logically less than + * another entity path (lexicographical order) + * + * Returns whether an entity path is logically less than another. + * This determination takes into account the entity path type, the + * number of path elements, and the values of the path elements + * themselves. + * + * @param[in] i_rhs Const reference to entity path to compare + * + * @pre N/A + * + * @post Equality returned to caller + * + * @return bool indicating whether an entity path is logically less + * than another entity path + * + * @retval true The lhs entity path is logically less than rhs + * @retval false The lhs entity path is logically greater than rhs + */ + bool operator<(const EntityPath& i_rhs) const; + + /** * @brief Returns whether two entity paths are logically equal, but * only for the specified number of path elements * diff --git a/src/include/usr/targeting/common/utilFilter.H b/src/include/usr/targeting/common/utilFilter.H index 0e381286d..021dceb74 100644 --- a/src/include/usr/targeting/common/utilFilter.H +++ b/src/include/usr/targeting/common/utilFilter.H @@ -34,7 +34,6 @@ #include <targeting/common/iterators/targetiterator.H> #include <targeting/common/iterators/rangefilter.H> - namespace TARGETING { @@ -59,7 +58,25 @@ namespace TARGETING * * @return bool, true if t1 HUID < t2 HUID, false otherwise */ -bool compareTargetHuid(TargetHandle_t t1, TargetHandle_t t2); +inline bool compareTargetHuid(TargetHandle_t t1, TargetHandle_t t2) +{ + return (t1->getAttr<ATTR_HUID>() < t2->getAttr<ATTR_HUID>()); +} + +/** + * @brief Predicate function to sort by Affinity path (lexicographical order) + * + * @parm[in] t1, Target 1 for AffinityPath comparison against target 2 + * @parm[in] t2, Target 2 for AffinityPath comparison against target 1 + * + * @return bool, true if t1 AffinityPath < t2 AffinityPath, false otherwise + */ +inline bool compareAffinity(TargetHandle_t t1, TargetHandle_t t2) +{ + EntityPath t1_Affinity = t1->getAttr<ATTR_AFFINITY_PATH>(); + EntityPath t2_Affinity = t2->getAttr<ATTR_AFFINITY_PATH>(); + return t1_Affinity < t2_Affinity; +} /** * @brief Populate the o_vector with target chip pointers based on the diff --git a/src/usr/hwas/common/deconfigGard.C b/src/usr/hwas/common/deconfigGard.C index a89f186ed..b188192a6 100644 --- a/src/usr/hwas/common/deconfigGard.C +++ b/src/usr/hwas/common/deconfigGard.C @@ -344,12 +344,6 @@ errlHndl_t DeconfigGard::deconfigureTargetsFromGardRecordsForIpl( } // deconfigureTargetsFromGardRecordsForIpl //****************************************************************************** -bool compareTargetHuid(TargetHandle_t t1, TargetHandle_t t2) -{ - return (t1->getAttr<ATTR_HUID>() < t2->getAttr<ATTR_HUID>()); -} - -//****************************************************************************** errlHndl_t DeconfigGard::processFieldCoreOverride() { HWAS_DBG("Process Field Core Override FCO"); diff --git a/src/usr/hwas/common/hwas.C b/src/usr/hwas/common/hwas.C index a74518faf..7dc95ff1b 100644 --- a/src/usr/hwas/common/hwas.C +++ b/src/usr/hwas/common/hwas.C @@ -45,7 +45,6 @@ #include <hwas/common/deconfigGard.H> #include <hwas/common/hwas_reasoncodes.H> #include <targeting/common/utilFilter.H> -#include <hwas/common/deconfigGard.H> namespace HWAS { @@ -66,10 +65,6 @@ TRAC_INIT(&g_trac_imp_hwas, "HWAS_I", 1024 ); #endif // SORT functions that we'll use for PR keyword processing -bool compareTargetHUID(TargetHandle_t t1, TargetHandle_t t2) -{ - return (t1->getAttr<ATTR_HUID>() < t2->getAttr<ATTR_HUID>()); -} bool compareProcGroup(procRestrict_t t1, procRestrict_t t2) { if (t1.group == t2.group) @@ -80,6 +75,11 @@ bool compareProcGroup(procRestrict_t t1, procRestrict_t t2) return (t1.group < t2.group); } +bool compareAffinity(const TargetInfo t1, const TargetInfo t2) +{ + return t1.affinityPath < t2.affinityPath; +} + /** * @brief simple helper fn to get and set hwas state to poweredOn, * present, functional @@ -183,7 +183,8 @@ errlHndl_t discoverTargets() // sort the list by ATTR_HUID to ensure that we // start at the same place each time std::sort(pCheckPres.begin(), pCheckPres.end(), - compareTargetHUID); + compareTargetHuid); + for (TargetHandleList::const_iterator pTarget_it = pCheckPres.begin(); pTarget_it != pCheckPres.end(); ++pTarget_it @@ -472,143 +473,10 @@ errlHndl_t discoverTargets() break; } - HWAS_INF("discoverTargets:Find functional MCSs" - " which should be non-functional "); - - //get the membufs - TargetHandleList l_funcMembufTargetList; - getAllChips(l_funcMembufTargetList, TYPE_MEMBUF, true ); - - //get the mcss - TargetHandleList l_funcMCSTargetList; - getAllChiplets(l_funcMCSTargetList, TYPE_MCS, true ); - - TargetHandleList::iterator pMCSTarget_it = l_funcMCSTargetList.begin(); - while (pMCSTarget_it != l_funcMCSTargetList.end()) - { - TargetHandle_t l_MCSTarget = *pMCSTarget_it; - EntityPath l_MCSAffinityPath = - l_MCSTarget->getAttr<ATTR_AFFINITY_PATH>(); - - bool l_functMembufFound = false; - HWAS_DBG("discoverTargets: MCS %.8X is functional", - l_MCSTarget->getAttr<ATTR_HUID>()); - - for (TargetHandleList::iterator - pMembufTarget_it = l_funcMembufTargetList.begin(); - pMembufTarget_it != l_funcMembufTargetList.end(); - ++pMembufTarget_it) - { - TargetHandle_t l_MembufTarget = *pMembufTarget_it; - EntityPath l_MembufAffinityPath = - l_MembufTarget->getAttr<ATTR_AFFINITY_PATH>(); - - l_functMembufFound = - l_MCSAffinityPath.equals(l_MembufAffinityPath, - l_MCSAffinityPath.size()); - if (l_functMembufFound == true) - { - //found a functional membuf so don't need to look further - //can also remove the membuf from the list since a membuf - //should not match two MCSs - pMembufTarget_it= - l_funcMembufTargetList.erase(pMembufTarget_it); - HWAS_DBG("discoverTargets: MEMBUF %.8X is " - "functional, assoicated with MCS %.8X", - l_MembufTarget->getAttr<ATTR_HUID>(), - l_MCSTarget->getAttr<ATTR_HUID>()); - break; - } - - } - if (l_functMembufFound) - { - //remove functional MCS associated with functional membufs from - //the list of functional MCS - pMCSTarget_it=l_funcMCSTargetList.erase(pMCSTarget_it); - } - else - { - ++pMCSTarget_it; - } - } - - //should now have a list of functional MCS that have no functional - //membufs - for (TargetHandleList::const_iterator - pMCSTarget_it = l_funcMCSTargetList.begin(); - pMCSTarget_it != l_funcMCSTargetList.end(); - ++pMCSTarget_it) - { - TargetHandle_t l_MCSTarget = *pMCSTarget_it; - //indicate that the MCS should be disabled because there is a - //non functional membuf or no membufs associated with this MCS - enableHwasState(l_MCSTarget,true,false, - HWAS::DeconfigGard::DECONFIGURED_BY_NO_CHILD_MEMBUF); - - - - HWAS_INF("discoverTargets: MCS %.8X mark as present, not functional", - l_MCSTarget->getAttr<ATTR_HUID>() ); - } - - // Get list of non-functional Centaurs - TargetHandleList l_nonFuncCentaurs; - getChipResources(l_nonFuncCentaurs, TYPE_MEMBUF, - UTIL_FILTER_NON_FUNCTIONAL); - - // Some common variables used below - TargetHandleList pChildList; - PredicateIsFunctional isFunctional; - - // Iterate through list of non-functional Centaurs, and - // set all children as non-functional - for (TargetHandleList::const_iterator - pCenTarget_it = l_nonFuncCentaurs.begin(); - pCenTarget_it != l_nonFuncCentaurs.end(); - ++pCenTarget_it) - { - // Cache current target - TargetHandle_t l_cenTarget = *pCenTarget_it; - - // find all CHILD matches for this target and deconfigure them - targetService().getAssociated(pChildList, l_cenTarget, - TargetService::CHILD, TargetService::ALL, &isFunctional); - for (TargetHandleList::iterator pChild_it = pChildList.begin(); - pChild_it != pChildList.end(); - ++pChild_it) - { - TargetHandle_t l_childTarget = *pChild_it; - //non functional membuf or no membufs associated with this MCS - enableHwasState(l_childTarget,true,false, - HWAS::DeconfigGard::DECONFIGURED_BY_NO_PARENT_MEMBUF); - HWAS_INF("discoverTargets: Target %.8X mark as present" - ", not functional due to non-functional parent" - " Centaur", - l_childTarget->getAttr<ATTR_HUID>() ); - } - - // find all CHILD_BY_AFFINITY matches for this target and - // deconfigure them - targetService().getAssociated(pChildList, l_cenTarget, - TargetService::CHILD_BY_AFFINITY, TargetService::ALL, - &isFunctional); - for (TargetHandleList::iterator pChild_it = pChildList.begin(); - pChild_it != pChildList.end(); - ++pChild_it) - { - TargetHandle_t l_affinityTarget = *pChild_it; - //non functional membuf or no membufs associated with this MCS - enableHwasState(l_affinityTarget,true,false, - HWAS::DeconfigGard::DECONFIGURED_BY_NO_PARENT_MEMBUF); - HWAS_INF("discoverTargets: Target %.8X mark as present" - ", not functional due to non-functional parent" - " Centaur", - l_affinityTarget->getAttr<ATTR_HUID>() ); - } - } - - + // call invokePresentByAssoc() to obtain functional MCS's, MEMBUFs, and + // DIMM's, call algorithm function presentByAssoc() to determine + // targets that need to be deconfigured + invokePresentByAssoc(); } while (0); @@ -688,7 +556,7 @@ errlHndl_t restrictEXunits( // sort the list by ATTR_HUID to ensure that we // start at the same place each time std::sort(pEXList[i].begin(), pEXList[i].end(), - compareTargetHUID); + compareTargetHuid); // keep a pointer into that list pEX_it[i] = pEXList[i].begin(); @@ -1077,5 +945,298 @@ errlHndl_t checkMinimumHardware(const TARGETING::ConstTargetHandle_t i_node) return l_errl ; } // checkMinimumHardware +/** + * @brief Checks if both targets have the same paths up to a certain number + * of path elements, determined by the smaller affinity path. + * + * @param[in] i_t1 TargetInfo containing the first target's affinity path + * @param[in] i_t2 TargetInfo containing the second target's affinity path + */ +bool isSameSubPath(TargetInfo i_t1, TargetInfo i_t2) +{ + size_t l_size = std::min(i_t1.affinityPath.size(), + i_t2.affinityPath.size()); + return i_t1.affinityPath.equals(i_t2.affinityPath, l_size); +} + +/** + * @brief Deconfigures a target based on type + * + * Called by invokePresentByAssoc() after presentByAssoc() is called + * + * @param[in] i_targInfo TargetInfo for the target to be deconfigured + */ +void deconfigPresentByAssoc(TargetInfo i_targInfo) +{ + TargetHandleList pChildList; + + // find all CHILD matches for this target and deconfigure them + getChildChiplets(pChildList, i_targInfo.pThisTarget, TYPE_NA); + + for (TargetHandleList::iterator pChild_it = pChildList.begin(); + pChild_it != pChildList.end(); + ++pChild_it) + { + TargetHandle_t l_childTarget = *pChild_it; + enableHwasState(l_childTarget, true, false, i_targInfo.reason); + HWAS_INF("deconfigPresentByAssoc: Target %.8X mark as present" + ", not functional due to non-functional parent" + " Centaur", + l_childTarget->getAttr<ATTR_HUID>() ); + } + + // find all CHILD_BY_AFFINITY matches for this target and deconfigure them + getChildAffinityTargets(pChildList, i_targInfo.pThisTarget, + CLASS_NA ,TYPE_NA); + + for (TargetHandleList::iterator pChild_it = pChildList.begin(); + pChild_it != pChildList.end(); + ++pChild_it) + { + TargetHandle_t l_affinityTarget = *pChild_it; + enableHwasState(l_affinityTarget,true,false, i_targInfo.reason); + HWAS_INF("deconfigPresentByAssoc: Target %.8X mark as present" + ", not functional due to non-functional parent" + " Centaur", + l_affinityTarget->getAttr<ATTR_HUID>() ); + } + + // deconfigure the target itself + enableHwasState(i_targInfo.pThisTarget,true,false,i_targInfo.reason); + HWAS_INF("deconfigPresentByAssoc: Target %.8X mark as present, not functional", + i_targInfo.huid ); + +} + +void invokePresentByAssoc() +{ + HWAS_INF("invokePresentByAssoc enter"); + + // make one list + TargetHandleList l_funcTargetList; + + // get the mcss + TargetHandleList l_funcMCSTargetList; + getAllChiplets(l_funcMCSTargetList, TYPE_MCS, true ); + l_funcTargetList.insert(l_funcTargetList.begin(), + l_funcMCSTargetList.begin(), + l_funcMCSTargetList.end()); + + // get the membufs + TargetHandleList l_funcMembufTargetList; + getAllChips(l_funcMembufTargetList, TYPE_MEMBUF, true ); + l_funcTargetList.insert(l_funcTargetList.begin(), + l_funcMembufTargetList.begin(), + l_funcMembufTargetList.end()); + + // get the dimms + TargetHandleList l_funcDIMMTargetList; + getAllLogicalCards(l_funcDIMMTargetList, TYPE_DIMM, true ); + l_funcTargetList.insert(l_funcTargetList.begin(), + l_funcDIMMTargetList.begin(), + l_funcDIMMTargetList.end()); + + // Define vectors of TargetInfo structs to be used in presentByAssoc + TargetInfoVector l_targInfo; + TargetInfoVector l_targToDeconfig; + do + { + // Iterate through targets and populate l_targInfo vector + for (TargetHandleList::const_iterator + l_targIter = l_funcTargetList.begin(); + l_targIter != l_funcTargetList.end(); + ++l_targIter) + { + TargetInfo l_TargetInfo; + l_TargetInfo.pThisTarget = + *l_targIter; + l_TargetInfo.affinityPath = + (*l_targIter)->getAttr<ATTR_AFFINITY_PATH>(); + l_TargetInfo.huid = + (*l_targIter)->getAttr<ATTR_HUID>(); + l_TargetInfo.type = + (*l_targIter)->getAttr<ATTR_TYPE>(); + l_TargetInfo.functional = true; + l_targInfo.push_back(l_TargetInfo); + } + + // Call presentByAssoc to take the functional targets in l_targInfo + // and determine which ones need to be deconfigured + presentByAssoc(l_targInfo, l_targToDeconfig); + + // Deconfigure targets in l_targToDeconfig + for (TargetInfoVector::const_iterator + l_targIter = l_targToDeconfig.begin(); + l_targIter != l_targToDeconfig.end(); + ++l_targIter) + { + deconfigPresentByAssoc(*l_targIter); + } + + } while(0); +} + +void presentByAssoc(TargetInfoVector& o_funcTargets, + TargetInfoVector& o_targToDeconfig) +{ + HWAS_INF("presentByAssoc entry"); + + // Sort entire vector by affinity path. This provides the algorithm with + // an ordered vector of targets, making it easy to check if a MCS has a + // MEMBUF, a MEMBUF has a MCS and DIMM, and a DIMM has a MEMBUF. + std::sort(o_funcTargets.begin(), o_funcTargets.end(), + compareAffinity); + + // Keep track of the most recently seen MCS and MEMBUF. This allows the + // algorithm to quickly check if targets share a MCS or MEMBUF and used + // for backtracking after deleting a target from the vector + size_t l_MCSIndex = __INT_MAX__; + size_t l_MEMBUFIndex = __INT_MAX__; + size_t i = 0; + + // Perform presentByAssoc algorithm + while ( i < o_funcTargets.size() ) + { + // INIT STEPS: + // Reset iterator, check functional state, check if the next taget in + // the vector is valid or even needed + + // Get iterator to erase elements from vector when needed + std::vector<TargetInfo>::iterator it = o_funcTargets.begin(); + std::advance(it,i); + + // If target is already marked non-functional, delete from vector and + // move on. + TargetInfo& l_curTargetInfo = *it; + if (!l_curTargetInfo.functional) + { + o_funcTargets.erase(it); + continue; + } + + // Check if there is a next target and set it + // Don't need to check next target with a DIMM + TargetInfo* l_nextTargetInfo = NULL; + if ( (i + 1) < o_funcTargets.size() && + l_curTargetInfo.type != TYPE_DIMM ) + { + l_nextTargetInfo = it + 1; + } + + // CASE MCS + if ( l_curTargetInfo.type == TYPE_MCS ) + { + // No Child MEMBUFs + // If next is not a MEMBUF sharing the same MCS, deconfig MCS + if ( l_nextTargetInfo == NULL || + l_nextTargetInfo->type != TYPE_MEMBUF || + !isSameSubPath(l_curTargetInfo, *l_nextTargetInfo) ) + { + // Disable MCS - NO_CHILD_MEMBUF + l_curTargetInfo.reason = + HWAS::DeconfigGard::DECONFIGURED_BY_NO_CHILD_MEMBUF; + + // Add target to Deconfig vector to be deconfigured later + o_targToDeconfig.push_back(l_curTargetInfo); + // Remove target from funcTargets + o_funcTargets.erase(it); + } + // Update MCS Index + else + { + l_MCSIndex = i; + i++; + } + } + + // CASE MEMBUF + else if ( l_curTargetInfo.type == TYPE_MEMBUF ) + { + // No Child DIMMs + // If next is not a DIMM sharing the same MEMBUF, deconfig MEMBUF + if ( l_nextTargetInfo == NULL || + l_nextTargetInfo->type != TYPE_DIMM || + !isSameSubPath(l_curTargetInfo, *l_nextTargetInfo) ) + { + // Disable MEMBUF - NO_CHILD_DIMM + l_curTargetInfo.reason = + HWAS::DeconfigGard::DECONFIGURED_BY_NO_CHILD_DIMM; + } + // No Parent MCS + // If MEMBUF doesn't share the same MCS as MCSIndex, deconfig MEMBUF + else if ( l_MCSIndex == __INT_MAX__ || + !isSameSubPath(l_curTargetInfo, o_funcTargets[l_MCSIndex])) + { + // Disable MEMBUF - NO_PARENT_MCS + l_curTargetInfo.reason = + HWAS::DeconfigGard::DECONFIGURED_BY_NO_PARENT_MCS; + } + // Update MEMBUF Index + else + { + l_MEMBUFIndex = i; + i++; + continue; + } + + // Add target to deconfig vector to be deconfigured later + o_targToDeconfig.push_back(l_curTargetInfo); + // Remove target from funcTargets + o_funcTargets.erase(it); + + // Backtrack to last MCS + if ( l_MCSIndex != __INT_MAX__ ) + { + i = l_MCSIndex; + } + // Backtrack to beginning if no MCS has been seen yet + else + { + i = 0; + } + } + + // CASE DIMM + else if ( l_curTargetInfo.type == TYPE_DIMM ) + { + // No Parent MEMBUF + // If DIMM does not share the same MEMBUF as MEMBUFIndex, + // deconfig DIMM + if ( l_MEMBUFIndex == __INT_MAX__ || + !isSameSubPath(l_curTargetInfo, o_funcTargets[l_MEMBUFIndex])) + { + // Disable DIMM + l_curTargetInfo.reason = + HWAS::DeconfigGard::DECONFIGURED_BY_NO_PARENT_MEMBUF; + + // Add target to deconfig vector to be deconfigured later + o_targToDeconfig.push_back(l_curTargetInfo); + // Remove target from funcTargets + o_funcTargets.erase(it); + + // Backtrack to last MEMBUF + if ( l_MEMBUFIndex != __INT_MAX__ ) + { + i = l_MEMBUFIndex; + } + // Backtrack to last MCS if no MEMBUF has been seen yet + else if ( l_MCSIndex != __INT_MAX__) + { + i = l_MCSIndex; + } + // Backtrack to beginning if no MCS has been seen yet + else + { + i = 0; + } + } + else + { + i++; + } + } + } // presentByAssoc algorithm +} + }; // end namespace diff --git a/src/usr/hwas/test/hwasGardTest.H b/src/usr/hwas/test/hwasGardTest.H index 5ed0c50a9..952c9e968 100644 --- a/src/usr/hwas/test/hwasGardTest.H +++ b/src/usr/hwas/test/hwasGardTest.H @@ -2855,6 +2855,315 @@ public: TS_FAIL("testDeconfigureAssocProc8: incorrect configuration returned"); } } + + /** + * @brief Test Deconfig Present Association 1 + */ + void testdeconfigPresentByAssoc1() + { + TS_TRACE(INFO_MRK "testDeconfigureAssocProc1: Started"); + // This tests the scenario where there is one mcs, membuff, and dimm + // This is done to ensure that the algorithm works on each edge case + + TargetInfoVector l_targInfo; + TargetInfoVector l_targToDeconfig; + TargetInfo l_TargetInfo; + + l_TargetInfo.pThisTarget = NULL; + EntityPath l_ep(TARGETING::EntityPath::PATH_AFFINITY); + l_TargetInfo.functional = 1; + + // MCS only + l_ep.addLast(TYPE_MCS, 0); + l_TargetInfo.affinityPath = l_ep; + l_TargetInfo.huid = 0; + l_TargetInfo.type = TYPE_MCS; + + l_targInfo.push_back(l_TargetInfo); + + presentByAssoc(l_targInfo, l_targToDeconfig); + + // MEMBUF only + l_ep.addLast(TYPE_MEMBUF, 0); + l_TargetInfo.affinityPath = l_ep; + l_TargetInfo.huid = 1; + l_TargetInfo.type = TYPE_MEMBUF; + l_targInfo.push_back(l_TargetInfo); + + presentByAssoc(l_targInfo, l_targToDeconfig); + + // DIMM only + l_ep.addLast(TYPE_DIMM, 0); + l_TargetInfo.affinityPath = l_ep; + l_TargetInfo.huid = 2; + l_TargetInfo.type = TYPE_DIMM; + l_targInfo.push_back(l_TargetInfo); + + presentByAssoc(l_targInfo, l_targToDeconfig); + + // Check result + if (l_targToDeconfig.size() == 3 && + l_targToDeconfig[0].huid == 0 && + l_targToDeconfig[1].huid == 1 && + l_targToDeconfig[2].huid == 2 ) + { + TS_TRACE(INFO_MRK "testdeconfigPresentByAssoc1: Success"); + } + else + { + TS_FAIL("testdeconfigPresentByAssoc1: incorrect configuration returned"); + } + } + + /** + * @brief Test Deconfig Present Association 2 + */ + void testdeconfigPresentByAssoc2() + { + TS_TRACE(INFO_MRK "testdeconfigPresentByAssoc2: Started"); + // This test the scenario where MCS Group 0 does not have a membuf and + // is marked for deconfigure. + + // User-defined number of targets + size_t NUM_TARGS = 4; + + // Input target vector + TargetInfoVector l_targets; + TargetInfo l_TargInfo; + EntityPath l_ep(TARGETING::EntityPath::PATH_AFFINITY); + l_TargInfo.affinityPath = l_ep; + l_targets.insert(l_targets.begin(), NUM_TARGS, l_TargInfo); + // Output target vector + TargetInfoVector l_targToDeconfig; + + // Add MCS Group 0 + l_targets[0].pThisTarget = NULL; + l_targets[0].functional = 1; + l_targets[0].affinityPath.addLast(TYPE_MCS, 0); + l_targets[0].huid = 0; + l_targets[0].type = TYPE_MCS; + + // Add MEMBUF Group 1 + l_targets[1].pThisTarget = NULL; + l_targets[1].functional = 1; + l_targets[1].affinityPath.addLast(TYPE_MCS, 1); + l_targets[1].affinityPath.addLast(TYPE_MEMBUF, 0); + l_targets[1].huid = 1; + l_targets[1].type = TYPE_MEMBUF; + + // Add DIMM Group 1 + l_targets[2].pThisTarget = NULL; + l_targets[2].functional = 1; + l_targets[2].affinityPath.addLast(TYPE_MCS, 1); + l_targets[2].affinityPath.addLast(TYPE_MEMBUF, 0); + l_targets[2].affinityPath.addLast(TYPE_DIMM, 0); + l_targets[2].huid = 2; + l_targets[2].type = TYPE_DIMM; + + // Add MCS Group 1 + l_targets[3].pThisTarget = NULL; + l_targets[3].functional = 1; + l_targets[3].affinityPath.addLast(TYPE_MCS, 1); + l_targets[3].huid = 3; + l_targets[3].type = TYPE_MCS; + + presentByAssoc(l_targets, l_targToDeconfig); + + // Check result + if (l_targToDeconfig.size() == 1 && + l_targToDeconfig[0].huid == 0 ) + { + TS_TRACE(INFO_MRK "testdeconfigPresentByAssoc2: Success"); + } + else + { + TS_FAIL("testdeconfigPresentByAssoc2: incorrect configuration returned"); + } + } + + /** + * @brief Test Deconfig Present Association 3 + */ + void testdeconfigPresentByAssoc3() + { + TS_TRACE(INFO_MRK "testdeconfigPresentByAssoc3: Started"); + // This test the scenario where MEMBUF Group 1 has no MCS and then + // DIMM Group 1 has no MEMBUF because MEMBUF 1 will be marked for + // deconfigure + + // User-defined number of targets + size_t NUM_TARGS = 5; + + // Input target vector + TargetInfoVector l_targets; + TargetInfo l_TargInfo; + EntityPath l_ep(TARGETING::EntityPath::PATH_AFFINITY); + l_TargInfo.affinityPath = l_ep; + l_targets.insert(l_targets.begin(), NUM_TARGS, l_TargInfo); + // Output target vector + TargetInfoVector l_targToDeconfig; + + // Add MCS Group 0 + l_targets[0].pThisTarget = NULL; + l_targets[0].functional = 1; + l_targets[0].affinityPath.addLast(TYPE_MCS, 0); + l_targets[0].huid = 0; + l_targets[0].type = TYPE_MCS; + + // Add MEMBUF Group 0 + l_targets[1].pThisTarget = NULL; + l_targets[1].functional = 1; + l_targets[1].affinityPath.addLast(TYPE_MCS, 0); + l_targets[1].affinityPath.addLast(TYPE_MEMBUF, 0); + l_targets[1].huid = 1; + l_targets[1].type = TYPE_MEMBUF; + + // Add MEMBUF Group 1 + l_targets[2].pThisTarget = NULL; + l_targets[2].functional = 1; + l_targets[2].affinityPath.addLast(TYPE_MCS, 1); + l_targets[2].affinityPath.addLast(TYPE_MEMBUF, 0); + l_targets[2].huid = 2; + l_targets[2].type = TYPE_MEMBUF; + + + // Add DIMM Group 0 + l_targets[3].pThisTarget = NULL; + l_targets[3].functional = 1; + l_targets[3].affinityPath.addLast(TYPE_MCS, 0); + l_targets[3].affinityPath.addLast(TYPE_MEMBUF, 0); + l_targets[3].affinityPath.addLast(TYPE_DIMM, 0); + l_targets[3].huid = 3; + l_targets[3].type = TYPE_DIMM; + + // Add DIMM Group 1 + l_targets[4].pThisTarget = NULL; + l_targets[4].functional = 1; + l_targets[4].affinityPath.addLast(TYPE_MCS, 1); + l_targets[4].affinityPath.addLast(TYPE_MEMBUF, 0); + l_targets[4].affinityPath.addLast(TYPE_DIMM, 0); + l_targets[4].huid = 4; + l_targets[4].type = TYPE_DIMM; + + presentByAssoc(l_targets, l_targToDeconfig); + + // Check result + if (l_targToDeconfig.size() == 2 && + l_targToDeconfig[0].huid == 2 && + l_targToDeconfig[1].huid == 4 ) + { + TS_TRACE(INFO_MRK "testdeconfigPresentByAssoc3: Success"); + } + else + { + TS_FAIL("testdeconfigPresentByAssoc3: incorrect configuration returned"); + } + } + + /** + * @brief Test Deconfig Present Association 4 + */ + void testdeconfigPresentByAssoc4() + { + TS_TRACE(INFO_MRK "testdeconfigPresentByAssoc4: Started"); + // This test the scenario where MEMBUF Group 0 has no DIMMs causing + // MCS Group 0 to also be deconfigured. + + // User-defined number of targets + size_t NUM_TARGS = 2; + + // Input target vector + TargetInfoVector l_targets; + TargetInfo l_TargInfo; + EntityPath l_ep(TARGETING::EntityPath::PATH_AFFINITY); + l_TargInfo.affinityPath = l_ep; + l_targets.insert(l_targets.begin(), NUM_TARGS, l_TargInfo); + // Output target vector + TargetInfoVector l_targToDeconfig; + + // Add MCS Group 0 + l_targets[0].pThisTarget = NULL; + l_targets[0].functional = 1; + l_targets[0].affinityPath.addLast(TYPE_MCS, 0); + l_targets[0].huid = 0; + l_targets[0].type = TYPE_MCS; + + // Add MEMBUF Group 0 + l_targets[1].pThisTarget = NULL; + l_targets[1].functional = 1; + l_targets[1].affinityPath.addLast(TYPE_MCS, 0); + l_targets[1].affinityPath.addLast(TYPE_MEMBUF, 0); + l_targets[1].huid = 1; + l_targets[1].type = TYPE_MEMBUF; + + presentByAssoc(l_targets, l_targToDeconfig); + + // Check result + if (l_targToDeconfig.size() == 2 && + l_targToDeconfig[0].huid == 1 && + l_targToDeconfig[1].huid == 0 ) + { + TS_TRACE(INFO_MRK "testdeconfigPresentByAssoc4: Success"); + } + else + { + TS_FAIL("testdeconfigPresentByAssoc4: incorrect configuration returned"); + } + } + + /** + * @brief Test Deconfig Present Association 5 + */ + void testdeconfigPresentByAssoc5() + { + TS_TRACE(INFO_MRK "testdeconfigPresentByAssoc5: Started"); + // This test the scenario where MEMBUF Group 0 and DIMM Group 0 having + // no MCS. This tests the MCSINDEX edge case because one never existed + + // User-defined number of targets + size_t NUM_TARGS = 2; + + // Input target vector + TargetInfoVector l_targets; + TargetInfo l_TargInfo; + EntityPath l_ep(TARGETING::EntityPath::PATH_AFFINITY); + l_TargInfo.affinityPath = l_ep; + l_targets.insert(l_targets.begin(), NUM_TARGS, l_TargInfo); + // Output target vector + TargetInfoVector l_targToDeconfig; + + // Add MEMBUF Group 0 + l_targets[0].pThisTarget = NULL; + l_targets[0].functional = 1; + l_targets[0].affinityPath.addLast(TYPE_MCS, 0); + l_targets[0].affinityPath.addLast(TYPE_MEMBUF, 0); + l_targets[0].huid = 0; + l_targets[0].type = TYPE_MEMBUF; + + // Add DIMM Group 0 + l_targets[1].pThisTarget = NULL; + l_targets[1].functional = 1; + l_targets[1].affinityPath.addLast(TYPE_MCS, 0); + l_targets[1].affinityPath.addLast(TYPE_MEMBUF, 0); + l_targets[1].affinityPath.addLast(TYPE_DIMM, 0); + l_targets[1].huid = 1; + l_targets[1].type = TYPE_DIMM; + + presentByAssoc(l_targets, l_targToDeconfig); + + // Check result + if (l_targToDeconfig.size() == 2 && + l_targToDeconfig[0].huid == 0 && + l_targToDeconfig[1].huid == 1 ) + { + TS_TRACE(INFO_MRK "testdeconfigPresentByAssoc5: Success"); + } + else + { + TS_FAIL("testdeconfigPresentByAssoc5: incorrect configuration returned"); + } + } + }; #endif diff --git a/src/usr/targeting/common/entitypath.C b/src/usr/targeting/common/entitypath.C index 6a58331a0..b670422a8 100644 --- a/src/usr/targeting/common/entitypath.C +++ b/src/usr/targeting/common/entitypath.C @@ -36,6 +36,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <algorithm> // This component #include <attributeenums.H> @@ -187,6 +188,36 @@ bool EntityPath::operator==( } //****************************************************************************** +// EntityPath::operator< +//****************************************************************************** + +bool EntityPath::operator<(const EntityPath &i_rhs) const +{ + #define TARG_FN "operator<(...)" + + if (iv_type != i_rhs.iv_type) + { + return iv_type < i_rhs.iv_type; + } + + size_t size = std::min(iv_size,i_rhs.iv_size)*sizeof(PathElement); + int result = memcmp(&iv_pathElement[0], &i_rhs.iv_pathElement[0], size); + + // lhs == rhs + if ( result == 0 ) + { + return iv_size < i_rhs.iv_size; + } + else + { + return ( result < 0 ); + } + + #undef TARG_FN +} + + +//****************************************************************************** // EntityPath::equals //****************************************************************************** diff --git a/src/usr/targeting/common/utilFilter.C b/src/usr/targeting/common/utilFilter.C index f460ff93b..6e3986ddb 100644 --- a/src/usr/targeting/common/utilFilter.C +++ b/src/usr/targeting/common/utilFilter.C @@ -46,14 +46,6 @@ namespace TARGETING #define TARG_CLASS "" - -// Predicate function for sorting by HUID -bool compareTargetHuid(TargetHandle_t t1, TargetHandle_t t2) -{ - return (t1->getAttr<ATTR_HUID>() < t2->getAttr<ATTR_HUID>()); -} - - /** * @brief Populate the o_vector with target object pointers based on the * requested class, type, and functional state. |