summaryrefslogtreecommitdiffstats
path: root/src/usr
diff options
context:
space:
mode:
authorBrian Horton <brianh@linux.ibm.com>2013-06-19 18:52:17 -0500
committerA. Patrick Williams III <iawillia@us.ibm.com>2013-07-10 16:23:50 -0500
commit36da1243a5e1026fe10de3194c167cb1ceeb77c8 (patch)
treed666ee803d606f530c39d043adc0bb038f528148 /src/usr
parent3837a7143776c6ea55fcda737e3425860c75a28c (diff)
downloadblackbird-hostboot-36da1243a5e1026fe10de3194c167cb1ceeb77c8.tar.gz
blackbird-hostboot-36da1243a5e1026fe10de3194c167cb1ceeb77c8.zip
HWAS support of Field Core Override (FCO)
. add FIELD_CORE_OVERRIDE attribute . add HWAS support of FCO to restrict EX units, if needed Change-Id: I93acc3453edf68ce7dceab03d11ee2a08d312b1d RTC: 45870 Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/5099 Tested-by: Jenkins Server Reviewed-by: MIKE J. JONES <mjjones@us.ibm.com> Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/usr')
-rw-r--r--src/usr/hwas/common/deconfigGard.C157
-rw-r--r--src/usr/hwas/common/hwas.C321
-rw-r--r--src/usr/hwas/hwasPlat.C56
-rw-r--r--src/usr/targeting/common/xmltohb/attribute_types.xml21
-rw-r--r--src/usr/targeting/common/xmltohb/target_types.xml1
5 files changed, 386 insertions, 170 deletions
diff --git a/src/usr/hwas/common/deconfigGard.C b/src/usr/hwas/common/deconfigGard.C
index 617a262f4..6a9313c1a 100644
--- a/src/usr/hwas/common/deconfigGard.C
+++ b/src/usr/hwas/common/deconfigGard.C
@@ -26,10 +26,13 @@
* @brief Implements the DeconfigGard class
*/
#include <stdint.h>
+#include <algorithm>
+#include <hwas/common/hwas.H>
#include <hwas/common/hwasCommon.H>
#include <hwas/common/deconfigGard.H>
#include <hwas/common/hwas_reasoncodes.H>
+#include <targeting/common/utilFilter.H>
// Trace definition
#define __COMP_TD__ g_trac_deconf
@@ -65,27 +68,43 @@ bool processDeferredDeconfig()
errlHndl_t collectGard(const TARGETING::PredicateBase *i_pPredicate)
{
HWAS_INF("collectGard entry" );
+ errlHndl_t errl = NULL;
- errlHndl_t errl = theDeconfigGard().clearGardRecordsForReplacedTargets();
-
- if (errl)
- {
- HWAS_ERR("ERROR: collectGard failed to clear GARD Records for replaced Targets");
- }
- else
+ do
{
+
+ errl = theDeconfigGard().clearGardRecordsForReplacedTargets();
+ if (errl)
+ {
+ HWAS_ERR("ERROR: collectGard failed to clear GARD Records for replaced Targets");
+ break;
+ }
+
errl = theDeconfigGard().
deconfigureTargetsFromGardRecordsForIpl(i_pPredicate);
-
if (errl)
{
HWAS_ERR("ERROR: collectGard failed to deconfigure Targets from GARD Records for IPL");
+ break;
}
- else
+
+ errl = theDeconfigGard().processFieldCoreOverride();
+ if (errl)
{
- HWAS_INF("collectGard completed successfully");
+ HWAS_ERR("ERROR: collectGard failed to process Field Core Override");
+ break;
}
}
+ while(0);
+
+ if (errl)
+ {
+ HWAS_INF("collectGard failed (plid 0x%X)", errl->plid());
+ }
+ else
+ {
+ HWAS_INF("collectGard completed successfully");
+ }
return errl;
}
@@ -296,6 +315,118 @@ errlHndl_t DeconfigGard::deconfigureTargetsFromGardRecordsForIpl(
return l_pErr;
}
+bool compareTargetHuid(TARGETING::TargetHandle_t t1,
+ TARGETING::TargetHandle_t t2)
+{
+ return (t1->getAttr<TARGETING::ATTR_HUID>() <
+ t2->getAttr<TARGETING::ATTR_HUID>());
+}
+
+//******************************************************************************
+errlHndl_t DeconfigGard::processFieldCoreOverride()
+{
+ HWAS_INF("Process Field Core Override FCO");
+ errlHndl_t l_pErr = NULL;
+
+ do
+ {
+ // otherwise, process and reduce cores.
+ // find all functional NODE targets
+ TARGETING::Target* pSys;
+ TARGETING::targetService().getTopLevelTarget(pSys);
+ TARGETING::PredicateCTM predNode(TARGETING::CLASS_ENC,
+ TARGETING::TYPE_NODE);
+ TARGETING::PredicateHwas predFunctional;
+ predFunctional.functional(true);
+ TARGETING::PredicatePostfixExpr nodeCheckExpr;
+ nodeCheckExpr.push(&predNode).push(&predFunctional).And();
+
+ TARGETING::TargetHandleList pNodeList;
+ TARGETING::targetService().getAssociated(pNodeList, pSys,
+ TARGETING::TargetService::CHILD,
+ TARGETING::TargetService::ALL,
+ &nodeCheckExpr);
+
+ // sort the list by ATTR_HUID to ensure that we
+ // start at the same place each time
+ std::sort(pNodeList.begin(), pNodeList.end(),
+ compareTargetHuid);
+
+ // for each of the nodes
+ for (TARGETING::TargetHandleList::const_iterator
+ pNode_it = pNodeList.begin();
+ pNode_it != pNodeList.end();
+ ++pNode_it
+ )
+ {
+ const TARGETING::TargetHandle_t pNode = *pNode_it;
+
+ // Get FCO value
+ uint32_t l_fco = 0;
+ l_pErr = platGetFCO(pNode, l_fco);
+ if (l_pErr)
+ {
+ HWAS_ERR("Error from platGetFCO");
+ break;
+ }
+
+ // FCO of 0 means no overrides for this node
+ if (l_fco == 0)
+ {
+ HWAS_INF("FCO: node %.8X: no overrides, done.",
+ TARGETING::get_huid(pNode));
+ continue; // next node
+ }
+
+ HWAS_INF("FCO: node %.8X: value %d",
+ TARGETING::get_huid(pNode), l_fco);
+
+ // find all functional child PROC targets
+ TARGETING::TargetHandleList pProcList;
+ TARGETING::getChildAffinityTargets(pProcList, pNode,
+ TARGETING::CLASS_CHIP, TARGETING::TYPE_PROC,
+ true);
+
+ // sort the list by ATTR_HUID to ensure that we
+ // start at the same place each time
+ std::sort(pProcList.begin(), pProcList.end(),
+ compareTargetHuid);
+
+ // create list for restrictEXunits() function
+ procRestrict_t l_procEntry;
+ std::vector <procRestrict_t> l_procRestrictList;
+ for (TARGETING::TargetHandleList::const_iterator
+ pProc_it = pProcList.begin();
+ pProc_it != pProcList.end();
+ ++pProc_it
+ )
+ {
+ const TARGETING::TargetHandle_t pProc = *pProc_it;
+
+ // save info so that we can
+ // restrict the number of EX units
+ HWAS_INF("pProc %.8X - pushing to proclist",
+ TARGETING::get_huid(pProc));
+ l_procEntry.target = pProc;
+ l_procEntry.group = 0;
+ l_procEntry.procs = pProcList.size();
+ l_procEntry.maxEXs = l_fco;
+ l_procRestrictList.push_back(l_procEntry);
+ } // for pProc_it
+
+ // restrict the EX units; units turned off are marked
+ // present=true, functional=false
+ HWAS_INF("FCO: calling restrictEXunits with %d entries",
+ l_procRestrictList.size());
+ l_pErr = restrictEXunits(l_procRestrictList, true);
+ break;
+ } // for pNode_it
+ }
+ while (0);
+
+ return l_pErr;
+}
+
//******************************************************************************
errlHndl_t DeconfigGard::deconfigureTarget(TARGETING::Target & i_target,
const uint32_t i_errlPlid,
@@ -500,7 +631,8 @@ void DeconfigGard::_deconfigureByAssoc(TARGETING::Target & i_target,
TARGETING::TargetService::CHILD,
TARGETING::TargetService::ALL,
&hwasPredicate);
- for (TARGETING::TargetHandleList::iterator pChild_it = pChildList.begin();
+ for (TARGETING::TargetHandleList::const_iterator
+ pChild_it = pChildList.begin();
pChild_it != pChildList.end();
++pChild_it)
{
@@ -516,7 +648,8 @@ void DeconfigGard::_deconfigureByAssoc(TARGETING::Target & i_target,
TARGETING::TargetService::CHILD_BY_AFFINITY,
TARGETING::TargetService::ALL,
&hwasPredicate);
- for (TARGETING::TargetHandleList::iterator pChild_it = pChildList.begin();
+ for (TARGETING::TargetHandleList::const_iterator
+ pChild_it = pChildList.begin();
pChild_it != pChildList.end();
++pChild_it)
{
diff --git a/src/usr/hwas/common/hwas.C b/src/usr/hwas/common/hwas.C
index 4e04ee86e..be642ca13 100644
--- a/src/usr/hwas/common/hwas.C
+++ b/src/usr/hwas/common/hwas.C
@@ -36,6 +36,7 @@
#include <algorithm>
#include <targeting/common/commontargeting.H>
+#include <targeting/common/utilFilter.H>
#include <hwas/common/hwas.H>
#include <hwas/common/hwasCommon.H>
@@ -59,22 +60,19 @@ TRAC_INIT(&g_trac_dbg_hwas, "HWAS", 1024 );
TRAC_INIT(&g_trac_imp_hwas, "HWAS_I", 1024 );
#endif
-// structure used to store proc information for PR keyword processing
-typedef struct {
- TargetHandle_t target;
- ATTR_FRU_ID_type fruid;
- uint8_t avgNum;
- uint8_t vpdCopies;
-} procPR_t;
-
// 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 compareProcFRUID(procPR_t t1, procPR_t t2)
+bool compareProcGroup(procRestrict_t t1, procRestrict_t t2)
{
- return (t1.fruid < t2.fruid);
+ if (t1.group == t2.group)
+ {
+ return (t1.target->getAttr<ATTR_HUID>() <
+ t2.target->getAttr<ATTR_HUID>());
+ }
+ return (t1.group < t2.group);
}
/**
@@ -173,10 +171,14 @@ errlHndl_t discoverTargets()
// and read and store values from the PR keyword
// list of procs and data that we'll need to look at the PR keyword
- procPR_t l_procEntry;
- std::vector <procPR_t> l_procPRList;
-
- for (TargetHandleList::iterator pTarget_it = pCheckPres.begin();
+ procRestrict_t l_procEntry;
+ std::vector <procRestrict_t> l_procPRList;
+
+ // sort the list by ATTR_HUID to ensure that we
+ // start at the same place each time
+ std::sort(pCheckPres.begin(), pCheckPres.end(),
+ compareTargetHUID);
+ for (TargetHandleList::const_iterator pTarget_it = pCheckPres.begin();
pTarget_it != pCheckPres.end();
++pTarget_it
)
@@ -291,12 +293,12 @@ errlHndl_t discoverTargets()
pTarget->getAttr<ATTR_HUID>(),
pTarget->getAttr<ATTR_FRU_ID>());
l_procEntry.target = pTarget;
- l_procEntry.fruid = pTarget->getAttr<ATTR_FRU_ID>();
- l_procEntry.avgNum =
+ l_procEntry.group = pTarget->getAttr<ATTR_FRU_ID>();
+ l_procEntry.procs =
+ (prData[7] & VPD_VINI_PR_B7_MASK) + 1;
+ l_procEntry.maxEXs = l_procEntry.procs *
(prData[2] & VPD_VINI_PR_B2_MASK)
>> VPD_VINI_PR_B2_SHIFT;
- l_procEntry.vpdCopies =
- (prData[7] & VPD_VINI_PR_B7_MASK) + 1;
l_procPRList.push_back(l_procEntry);
}
}
@@ -312,7 +314,7 @@ errlHndl_t discoverTargets()
TargetHandleList pDescList;
targetService().getAssociated( pDescList, pTarget,
TargetService::CHILD, TargetService::ALL);
- for (TargetHandleList::iterator pDesc_it = pDescList.begin();
+ for (TargetHandleList::const_iterator pDesc_it = pDescList.begin();
pDesc_it != pDescList.end();
++pDesc_it)
{
@@ -419,156 +421,187 @@ errlHndl_t discoverTargets()
// PR keyword processing - potentially reduce the number of ex/core
// units that are functional based on what's in the PR keyword.
+ // call to restrict EX units, marking bad units as present=false;
+ errl = restrictEXunits(l_procPRList, false);
- // predicate to find present EX units
- PredicateCTM predEX(CLASS_UNIT, TYPE_EX);
- PredicateHwas predPresent;
- predPresent.present(true);
- PredicatePostfixExpr exCheckExpr;
- exCheckExpr.push(&predEX).push(&predPresent).And();
-
- // predicate to find CORE units
- PredicateCTM predCore(CLASS_UNIT, TYPE_CORE);
- PredicatePostfixExpr coreCheckExpr;
- coreCheckExpr.push(&predCore);
-
- // sort by ATTR_FRU_ID so PROC# are in the right groupings.
- std::sort(l_procPRList.begin(), l_procPRList.end(),
- compareProcFRUID);
-
- // AFTER all targets have been tested, loop thru procs to handle PR
- const uint32_t l_PRProcCount = l_procPRList.size();
- for (uint32_t procIdx = 0;
- procIdx < l_PRProcCount;
- // the increment will happen in the loop to handle
- // PR records covering more than 1 proc target
- )
- {
- // determine the number of procs we should enable
- uint8_t avgNum = l_procPRList[procIdx].avgNum;
- uint8_t vpdCopies = l_procPRList[procIdx].vpdCopies;
+ } while (0);
+
+ if (errl)
+ {
+ HWAS_INF("discoverTargets failed (plid 0x%X)", errl->plid());
+ }
+ else
+ {
+ HWAS_INF("discoverTargets completed successfully");
+ }
+ return errl;
+} // discoverTargets
- // this procs FRU_ID, used to determine groupings
- ATTR_FRU_ID_type thisFruId = l_procPRList[procIdx].fruid;
- HWAS_INF("procPRList[%d] - PR avg units %d, VPDs %d, FRU_ID %d",
- procIdx, avgNum, vpdCopies, thisFruId);
+errlHndl_t restrictEXunits(
+ std::vector <procRestrict_t> &i_procList,
+ bool i_present)
+{
+ HWAS_INF("restrictEXunits entry, %d elements", i_procList.size());
+ errlHndl_t errl = NULL;
- // exs and iters for each proc in this vpd set
- TargetHandleList pEXList[vpdCopies];
- TargetHandleList::iterator pEX_it[vpdCopies];
+ // sort by group so PROC# are in the right groupings.
+ std::sort(i_procList.begin(), i_procList.end(),
+ compareProcGroup);
+
+ // loop thru procs to handle restrict
+ const uint32_t l_ProcCount = i_procList.size();
+ for (uint32_t procIdx = 0;
+ procIdx < l_ProcCount;
+ // the increment will happen in the loop to handle
+ // groups covering more than 1 proc target
+ )
+ {
+ // determine the number of procs we should enable
+ uint8_t procs = i_procList[procIdx].procs;
+ uint32_t maxEXs = i_procList[procIdx].maxEXs;
- // find the proc's that we think are in this group
- for (uint32_t i = 0; i < vpdCopies; i++)
- {
- TargetHandle_t pProc = l_procPRList[procIdx].target;
+ // this procs number, used to determine groupings
+ uint32_t thisGroup = i_procList[procIdx].group;
- // if this proc is past the last of the proc count
- // OR is NOT in the same FRU_ID
- if ((procIdx >= l_PRProcCount) ||
- (thisFruId != pProc->getAttr<ATTR_FRU_ID>()))
- {
- HWAS_DBG("procPRList[%d] - not in FRU_ID %d group",
- i, thisFruId);
+ HWAS_INF("procRestrictList[%d] - maxEXs %d, procs %d, group %d",
+ procIdx, maxEXs, procs, thisGroup);
- // change this to be how many we actually have here
- vpdCopies = i;
+ // exs and iters for each proc in this vpd set
+ TargetHandleList pEXList[procs];
+ TargetHandleList::const_iterator pEX_it[procs];
- // we're done - break so that we use procIdx as the
- // start index next time
- break;
- }
+ // find the proc's that we think are in this group
+ uint32_t currentEXs = 0;
+ for (uint32_t i = 0; i < procs; ) // increment in loop
+ {
+ TargetHandle_t pProc = i_procList[procIdx].target;
- // get this proc's (CHILD) present EX units
- targetService().getAssociated( pEXList[i], pProc,
- TargetService::CHILD, TargetService::ALL, &exCheckExpr);
+ // if this proc is past the last of the proc count
+ // OR is NOT in the same group
+ if ((procIdx >= l_ProcCount) ||
+ (thisGroup != i_procList[procIdx].group))
+ {
+ HWAS_DBG("procRestrictList[%d] - group %d not in group %d",
+ i, i_procList[procIdx].group, thisGroup);
- if (!pEXList[i].empty())
- {
- // 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);
+ // change this to be how many we actually have here
+ procs = i;
- // keep a pointer into that list
- pEX_it[i] = pEXList[i].begin();
- }
- else
- {
- // this one is bad, so decrement the counters
- vpdCopies--;
- i--;
- }
+ // we're done - break so that we use procIdx as the
+ // start index next time
+ break;
+ }
- // advance the outer loop as well since we're doing these
- // procs together
- ++procIdx;
- } // for
+ // get this proc's (CHILD) functional EX units
+ getChildChiplets(pEXList[i], pProc, TYPE_EX, true);
- // now need to find EX units that stay function, going
- // across the list of units for each proc we have, until
- // we get to the max or run out of EXs.
- uint8_t procs_remaining = vpdCopies;
- uint32_t maxEXs = avgNum * vpdCopies;
- uint32_t goodEXs = 0;
- HWAS_DBG("vpdCopies %d maxEXs %d", vpdCopies, maxEXs);
- do
+ if (!pEXList[i].empty())
{
- // now cycle thru the procs
- for (uint32_t i = 0;i < vpdCopies;i++)
- {
- // if we have EX units still to process
- // from this processor
- if (pEX_it[i] != pEXList[i].end())
- {
- // got a present EX
- goodEXs++;
- HWAS_DBG("pEX %.8X - is good %d!",
- (*(pEX_it[i]))->getAttr<ATTR_HUID>(), goodEXs);
+ // 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);
- (pEX_it[i])++; // next ex/core in this proc's list
+ // keep a pointer into that list
+ pEX_it[i] = pEXList[i].begin();
- // check to see if we just hit the end of the list
- if (pEX_it[i] == pEXList[i].end())
- {
- procs_remaining--;
- continue;
- }
- }
- } // for
+ // keep local count of current functional EX units
+ currentEXs += pEXList[i].size();
+
+ // go to next proc
+ i++;
+ }
+ else
+ {
+ // this one is bad, stay on this i but lower the end count
+ procs--;
}
- while ((goodEXs < maxEXs) && (procs_remaining != 0));
- // now mark the rest of the EXs as non-present/non-functional
- for (uint32_t i = 0;i < vpdCopies;i++)
+ // advance the outer loop as well since we're doing these
+ // procs together
+ ++procIdx;
+ } // for
+
+ if (currentEXs <= maxEXs)
+ {
+ // we don't need to restrict - we're done with this group.
+ HWAS_DBG("currentEXs %d <= maxEXs %d -- done",
+ currentEXs, maxEXs);
+ continue;
+ }
+
+ HWAS_DBG("currentEXs %d > maxEXs %d -- restricting!",
+ currentEXs, maxEXs);
+
+ // now need to find EX units that stay function, going
+ // across the list of units for each proc we have, until
+ // we get to the max or run out of EXs.
+ uint8_t procs_remaining = procs;
+ uint32_t goodEXs = 0;
+ HWAS_DBG("procs %d maxEXs %d", procs, maxEXs);
+ do
+ {
+ // now cycle thru the procs, stopping when we either hit
+ // the end, or when we hit our maxEXs limit
+ for (uint32_t i = 0;(i < procs) && (goodEXs < maxEXs);i++)
{
- // walk thru the rest of the EX list
- while (pEX_it[i] != pEXList[i].end())
+ // if we have EX units still to process
+ // from this processor
+ if (pEX_it[i] != pEXList[i].end())
{
- TargetHandle_t l_pEX = *(pEX_it[i]);
- enableHwasState(l_pEX, false, false, 0);
- HWAS_INF("pEX %.8X - marked NOT present, NOT functional (PR)",
- l_pEX->getAttr<ATTR_HUID>());
-
- // now need to mark the child CORE
- TargetHandleList pCoreList;
- targetService().getAssociated(
- pCoreList, l_pEX,
- TargetService::CHILD, TargetService::ALL,
- &coreCheckExpr );
- enableHwasState(pCoreList[0], false, false, 0);
- HWAS_INF("pCore %.8X - marked NOT present, NOT functional (PR)",
- pCoreList[0]->getAttr<ATTR_HUID>());
+ // got a functional EX
+ goodEXs++;
+ HWAS_DBG("pEX %.8X - is good %d!",
+ (*(pEX_it[i]))->getAttr<ATTR_HUID>(), goodEXs);
+
(pEX_it[i])++; // next ex/core in this proc's list
+
+ // check to see if we just hit the end of the list
+ if (pEX_it[i] == pEXList[i].end())
+ {
+ procs_remaining--;
+ continue;
+ }
}
- } // for making remaining non-present/non-functional
- } // for procIdx < l_PRProcCount
+ } // for
+ }
+ while ((goodEXs < maxEXs) && (procs_remaining != 0));
- } while (0);
+ // now mark the rest of the EXs as non-functional
+ for (uint32_t i = 0;i < procs;i++)
+ {
+ // walk thru the rest of the EX list
+ while (pEX_it[i] != pEXList[i].end())
+ {
+ TargetHandle_t l_pEX = *(pEX_it[i]);
+ enableHwasState(l_pEX, i_present, false, 0);
+ HWAS_INF("pEX %.8X - marked %spresent, NOT functional",
+ l_pEX->getAttr<ATTR_HUID>(),
+ i_present ? "" : "NOT ");
+
+ // now need to mark the child CORE
+ TargetHandleList pCoreList;
+ getChildChiplets(pCoreList, l_pEX, TYPE_CORE, true);
+ enableHwasState(pCoreList[0], i_present, false, 0);
+ HWAS_INF("pCore %.8X - marked %spresent, NOT functional",
+ l_pEX->getAttr<ATTR_HUID>(),
+ i_present ? "" : "NOT ");
+ (pEX_it[i])++; // next ex/core in this proc's list
+ }
+ } // for making remaining non-functional
+ } // for procIdx < l_ProcCount
- HWAS_INF("discoverTargets returning errl %p", errl);
+ if (errl)
+ {
+ HWAS_INF("restrictEXunits failed (plid 0x%X)", errl->plid());
+ }
+ else
+ {
+ HWAS_INF("restrictEXunits completed successfully");
+ }
return errl;
-} // discoverTargets
+} // restrictEXunits
}; // end namespace
diff --git a/src/usr/hwas/hwasPlat.C b/src/usr/hwas/hwasPlat.C
index 2371fca68..d3b736a94 100644
--- a/src/usr/hwas/hwasPlat.C
+++ b/src/usr/hwas/hwasPlat.C
@@ -77,8 +77,8 @@ errlHndl_t platReadIDEC(const TargetHandle_t &i_target)
// using SCOM path. We must use FSI path to read the IDEC values.
// For master proc, use scom
// For everything else, use FSI(0x1028)
- TARGETING::Target* l_pMasterProcChip = NULL;
- TARGETING::targetService(). masterProcChipTargetHandle(l_pMasterProcChip);
+ Target* l_pMasterProcChip = NULL;
+ targetService().masterProcChipTargetHandle(l_pMasterProcChip);
if (i_target == l_pMasterProcChip)
{
@@ -161,11 +161,19 @@ errlHndl_t platReadPartialGood(const TargetHandle_t &i_target,
// skip past the header
uint16_t *pgData = reinterpret_cast <uint16_t *>(&pgRaw[VPD_CP00_PG_HDR_LENGTH]);
if (i_target->getAttr<ATTR_HUID>() == 0x50000)
- { // 1st proc - let it go thru ok.
+ { // 1st proc
+ pgData[VPD_CP00_PG_EX0_INDEX+4] = 0xF300;
+ pgData[VPD_CP00_PG_EX0_INDEX+5] = 0xF300;
+ pgData[VPD_CP00_PG_EX0_INDEX+6] = 0x9300; // off
+ pgData[VPD_CP00_PG_EX0_INDEX+12] = 0x9300; // off
+ pgData[VPD_CP00_PG_EX0_INDEX+13] = 0x9300; // off
+ pgData[VPD_CP00_PG_EX0_INDEX+14] = 0x9300; // off
}
else
if (i_target->getAttr<ATTR_HUID>() == 0x50001)
- {
+ { // 2nd proc
+ pgData[VPD_CP00_PG_EX0_INDEX+4] = 0xF300;
+ pgData[VPD_CP00_PG_EX0_INDEX+5] = 0xF300;
pgData[VPD_CP00_PG_EX0_INDEX+6] = 0xF300;
pgData[VPD_CP00_PG_EX0_INDEX+12] = 0xF300;
pgData[VPD_CP00_PG_EX0_INDEX+13] = 0xF300;
@@ -178,17 +186,22 @@ errlHndl_t platReadPartialGood(const TargetHandle_t &i_target,
//// should be marked present and NOT functional
////pgData[VPD_CP00_PG_PERVASIVE_INDEX] = 0;
- //pgData[VPD_CP00_PG_EX0_INDEX+12] = 0xF300;
+ pgData[VPD_CP00_PG_EX0_INDEX+4] = 0xF300;
+ pgData[VPD_CP00_PG_EX0_INDEX+5] = 0xF300;
+ pgData[VPD_CP00_PG_EX0_INDEX+6] = 0x9300; // off
+ pgData[VPD_CP00_PG_EX0_INDEX+12] = 0x9300; // off
pgData[VPD_CP00_PG_EX0_INDEX+13] = 0xF300;
pgData[VPD_CP00_PG_EX0_INDEX+14] = 0xF300;
}
else
if (i_target->getAttr<ATTR_HUID>() == 0x50003)
{ // 4th proc - EX13 and EX14 are good
- pgData[VPD_CP00_PG_EX0_INDEX+6] = 0xF300;
- pgData[VPD_CP00_PG_EX0_INDEX+12] = 0xF300;
- pgData[VPD_CP00_PG_EX0_INDEX+13] = 0xF300;
- pgData[VPD_CP00_PG_EX0_INDEX+14] = 0xF300;
+ pgData[VPD_CP00_PG_EX0_INDEX+4] = 0xF300;
+ pgData[VPD_CP00_PG_EX0_INDEX+5] = 0xF300;
+ pgData[VPD_CP00_PG_EX0_INDEX+6] = 0x9300; // off
+ pgData[VPD_CP00_PG_EX0_INDEX+12] = 0x9300; // off
+ pgData[VPD_CP00_PG_EX0_INDEX+13] = 0x9300; // off
+ pgData[VPD_CP00_PG_EX0_INDEX+14] = 0x9300; // off
}
}
#endif
@@ -234,7 +247,7 @@ errlHndl_t platReadPR(const TargetHandle_t &i_target,
if (i_target->getAttr<ATTR_HUID>() == 0x50000)
{ // 1st proc - let it go thru ok.
prData[2] = 3 << VPD_VINI_PR_B2_SHIFT; // 3*2 = 6 cores
- prData[7] = 0; // 2 procs
+ prData[7] = 1; // 2 procs
//prData[2] = 1 << VPD_VINI_PR_B2_SHIFT; // 1*4 = 4 cores
//prData[7] = 3; // 4 cores
}
@@ -249,16 +262,16 @@ errlHndl_t platReadPR(const TargetHandle_t &i_target,
else
if (i_target->getAttr<ATTR_HUID>() == 0x50002)
{ // 3rd proc -
- prData[2] = 3 << VPD_VINI_PR_B2_SHIFT; // 3*2 = 6 cores
- prData[7] = 0; // 2 procs
+ prData[2] = 3 << VPD_VINI_PR_B2_SHIFT; // 3*1 = 3 cores
+ prData[7] = 0; // 1 procs
//prData[2] = 1 << VPD_VINI_PR_B2_SHIFT; // 1*4 = 4 cores
//prData[7] = 3; // 4 cores
}
else
if (i_target->getAttr<ATTR_HUID>() == 0x50003)
{ // 4th proc -
- prData[2] = 3 << VPD_VINI_PR_B2_SHIFT; // 3*2 = 6 cores
- prData[7] = 0; // 2 procs
+ prData[2] = 4 << VPD_VINI_PR_B2_SHIFT; // 4*1 = 4 cores
+ prData[7] = 0; // 1 procs
//prData[2] = 1 << VPD_VINI_PR_B2_SHIFT; // 1*4 = 4 cores
//prData[7] = 3; // 4 cores
}
@@ -274,6 +287,21 @@ errlHndl_t platReadPR(const TargetHandle_t &i_target,
} // platReadPR
//******************************************************************************
+// platGetFCO function
+//******************************************************************************
+errlHndl_t platGetFCO(const TargetHandle_t &i_node,
+ uint32_t &o_fco)
+{
+ errlHndl_t errl = NULL;
+
+ o_fco = i_node->getAttr<ATTR_FIELD_CORE_OVERRIDE>();
+
+ HWAS_INF("FCO returned: %d", o_fco);
+
+ return errl;
+} // platGetFCO
+
+//******************************************************************************
// platPresenceDetect function
//******************************************************************************
errlHndl_t platPresenceDetect(TargetHandleList &io_targets)
diff --git a/src/usr/targeting/common/xmltohb/attribute_types.xml b/src/usr/targeting/common/xmltohb/attribute_types.xml
index 8a1ca787b..77afa1c8e 100644
--- a/src/usr/targeting/common/xmltohb/attribute_types.xml
+++ b/src/usr/targeting/common/xmltohb/attribute_types.xml
@@ -12605,4 +12605,25 @@ firmware notes: Platforms should initialize this attribute to AUTO (0)</descript
</enumerator>
</enumerationType>
+<attribute>
+ <id>FIELD_CORE_OVERRIDE</id>
+ <description>Field Core Override (FCO) is the override value for the
+ number of functional cores allowed on the system.
+ FCO is used when customers order a system with N cores but they only want
+ to enable less than N cores to lower software license costs. A field in the
+ anchor VPD is set by manufacturing to specify the maximum number of cores
+ to enable. The number is maintained, even if some cores are garded out due
+ to error.
+ A value of 0 means all cores allowed;
+ </description>
+ <simpleType>
+ <uint32_t>
+ <default>0</default>
+ </uint32_t>
+ </simpleType>
+ <persistency>non-volatile</persistency>
+ <readable/>
+ <writeable/>
+</attribute>
+
</attributes>
diff --git a/src/usr/targeting/common/xmltohb/target_types.xml b/src/usr/targeting/common/xmltohb/target_types.xml
index 46a4c4131..99553c49a 100644
--- a/src/usr/targeting/common/xmltohb/target_types.xml
+++ b/src/usr/targeting/common/xmltohb/target_types.xml
@@ -651,6 +651,7 @@
<id>MODEL</id>
<default>POWER8</default>
</attribute>
+ <attribute><id>FIELD_CORE_OVERRIDE</id></attribute>
</targetType>
<targetType>
OpenPOWER on IntegriCloud