summaryrefslogtreecommitdiffstats
path: root/src/usr/vpd
diff options
context:
space:
mode:
authorwhs <whs@us.ibm.com>2016-03-14 16:31:27 -0500
committerStephen Cprek <smcprek@us.ibm.com>2016-04-21 13:51:47 -0500
commit9dee05c3d4c801d74972216a8c501e5c1c3fc2b6 (patch)
tree4acaf595a78857f595acdd9b17f03fd118411079 /src/usr/vpd
parent25bc87d9fc30db27f8c78019858f832c92d69097 (diff)
downloadblackbird-hostboot-9dee05c3d4c801d74972216a8c501e5c1c3fc2b6.tar.gz
blackbird-hostboot-9dee05c3d4c801d74972216a8c501e5c1c3fc2b6.zip
VPD Caching broken on multiple socket, single CVPD systems (Barreleye)
Invalidate Centaur Pnor sections if the section is invalid for all targets that share that section. Keep a section if any target sharing the section finds the section valid. Fixes: open-power/hostboot#29 Change-Id: I14302e38f1d39f3bb4e1857267e1547d1a06302b Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/22047 Tested-by: Jenkins Server Reviewed-by: A. P. Williams III <iawillia@us.ibm.com> Reviewed-by: Matthew A. Ploetz <maploetz@us.ibm.com> Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/22153 Tested-by: FSP CI Jenkins Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/usr/vpd')
-rw-r--r--src/usr/vpd/dvpd.C15
-rw-r--r--src/usr/vpd/pvpd.C18
-rwxr-xr-xsrc/usr/vpd/vpd.C128
3 files changed, 146 insertions, 15 deletions
diff --git a/src/usr/vpd/dvpd.C b/src/usr/vpd/dvpd.C
index b8c49a8ed..9ce09990f 100644
--- a/src/usr/vpd/dvpd.C
+++ b/src/usr/vpd/dvpd.C
@@ -265,13 +265,14 @@ errlHndl_t directMemoryPresenceDetect(DeviceFW::OperationType i_opType,
TRACFCOMP(g_trac_vpd,
ERR_MRK "directMemoryPresenceDetect> failed presence detect");
- // Invalidate DVPD in the PNOR
- l_errl = VPD::invalidatePnorCache(i_target);
- if (l_errl)
- {
- TRACFCOMP( g_trac_vpd, "Error invalidating DVPD in PNOR" );
- errlCommit( l_errl, VPD_COMP_ID );
- }
+ // Defer invalidating DVPD in the PNOR in case another target might be
+ // sharing this VPD_REC_NUM. Check all targets sharing this
+ // VPD_REC_NUM after target discovery in VPD::validateSharedPnorCache.
+ // Ensure the VPD_SWITCHES cache valid bit is invalid at this point.
+ TARGETING::ATTR_VPD_SWITCHES_type vpdSwitches =
+ i_target->getAttr<TARGETING::ATTR_VPD_SWITCHES>();
+ vpdSwitches.pnorCacheValid = 0;
+ i_target->setAttr<TARGETING::ATTR_VPD_SWITCHES>( vpdSwitches );
}
#endif
diff --git a/src/usr/vpd/pvpd.C b/src/usr/vpd/pvpd.C
index 3acde7831..8017776b9 100644
--- a/src/usr/vpd/pvpd.C
+++ b/src/usr/vpd/pvpd.C
@@ -262,14 +262,16 @@ errlHndl_t nodePresenceDetect(DeviceFW::OperationType i_opType,
TRACFCOMP(g_trac_vpd,
ERR_MRK "nodePresenceDetect> failed presence detect");
- // Invalidate PVPD in the PNOR
- l_errl = VPD::invalidatePnorCache(i_target);
- if (l_errl)
- {
- TRACFCOMP( g_trac_vpd, "Error invalidating PVPD in PNOR" );
- errlCommit( l_errl, VPD_COMP_ID );
- }
- pvpd_present = true;
+ // Defer invalidating PVPD in the PNOR in case another target might be
+ // sharing this VPD_REC_NUM. Check all targets sharing this
+ // VPD_REC_NUM after target discovery in VPD::validateSharedPnorCache.
+ // Ensure the VPD_SWITCHES cache valid bit is invalid at this point.
+ TARGETING::ATTR_VPD_SWITCHES_type vpdSwitches =
+ i_target->getAttr<TARGETING::ATTR_VPD_SWITCHES>();
+ vpdSwitches.pnorCacheValid = 0;
+ i_target->setAttr<TARGETING::ATTR_VPD_SWITCHES>( vpdSwitches );
+
+ pvpd_present = true; //node PVDP always returns present
}
#endif
diff --git a/src/usr/vpd/vpd.C b/src/usr/vpd/vpd.C
index b39361b45..ebda849d4 100755
--- a/src/usr/vpd/vpd.C
+++ b/src/usr/vpd/vpd.C
@@ -37,6 +37,7 @@
#include "pvpd.H"
#include "spd.H"
#include "ipvpd.H"
+#include <map>
// ----------------------------------------------
// Trace - defined in vpd_common
@@ -833,5 +834,132 @@ errlHndl_t invalidateAllPnorCaches ( bool i_setHwOnly )
return l_err;
}
+typedef std::pair<TARGETING::Target *, bool> targetValidPair_t;
+typedef std::map<TARGETING::ATTR_VPD_REC_NUM_type,
+ targetValidPair_t> numRecValidMap_t;
+
+// For each target in list, either add a map entry for this VPD_REC_NUM
+// or OR in the cache valid bit if VPD_REC_NUM is already in the map.
+void addListToMap(numRecValidMap_t & i_recNumMap,
+ const TARGETING::TargetHandleList & i_targetList)
+{
+ for (TARGETING::TargetHandleList::const_iterator
+ targItr = i_targetList.begin();
+ targItr != i_targetList.end();
+ ++targItr)
+ {
+ TARGETING::Target * l_pTarg = *targItr;
+ TARGETING::ATTR_VPD_REC_NUM_type l_recNum =
+ l_pTarg->getAttr<TARGETING::ATTR_VPD_REC_NUM>();
+ TARGETING::ATTR_VPD_SWITCHES_type l_switches =
+ l_pTarg->getAttr<TARGETING::ATTR_VPD_SWITCHES>();
+
+ numRecValidMap_t::iterator itr = i_recNumMap.find(l_recNum);
+ if( itr != i_recNumMap.end() )
+ {
+ TRACDCOMP( g_trac_vpd, "addListToMap() "
+ "OR in %d for VPD_REC_NUM %d HUID %.8X",
+ l_switches.pnorCacheValid,
+ l_recNum,
+ TARGETING::get_huid(l_pTarg));
+
+ itr->second.second |= l_switches.pnorCacheValid;
+ }
+ else
+ {
+ TRACDCOMP( g_trac_vpd, "addListToMap() "
+ "Set %d for VPD_REC_NUM %d HUID %.8X",
+ l_switches.pnorCacheValid,
+ l_recNum,
+ TARGETING::get_huid(l_pTarg));
+
+ i_recNumMap[l_recNum] =
+ targetValidPair_t(l_pTarg,l_switches.pnorCacheValid);
+ }
+ }
+}
+
+// --------------------------------------------------------
+// This function validates targets sharing the PNOR::CENTAUR_VPD cache.
+// Invalidate sections where all of the targets sharing a VPD_REC_NUM
+// are invalid. Keep the section if any target is valid.
+//---------------------------------------------------------
+errlHndl_t validateSharedPnorCache()
+{
+ errlHndl_t errl = NULL;
+ std::map<TARGETING::ATTR_VPD_REC_NUM_type,targetValidPair_t> l_recNumMap;
+
+ TRACDCOMP( g_trac_vpd, ENTER_MRK"validateSharedPnorCache()");
+
+ do
+ {
+#if defined(CONFIG_PVPD_READ_FROM_HW) && defined(CONFIG_PVPD_READ_FROM_PNOR)
+ // Add cache status for the node
+ TARGETING::TargetHandleList l_nodeList;
+ getEncResources(l_nodeList,
+ TARGETING::TYPE_NODE,
+ TARGETING::UTIL_FILTER_ALL);
+ addListToMap( l_recNumMap, l_nodeList);
+#endif
+
+ // If this system has mem bufs, then gather all mem bufs.
+ // If there are no mem bufs, then gather the MCSs for direct memory.
+ TARGETING::TargetHandleList l_memBufList;
+ getChipResources(l_memBufList,
+ TARGETING::TYPE_MEMBUF,
+ TARGETING::UTIL_FILTER_ALL);
+ if (l_memBufList.size()) // system has mem bufs
+ {
+ addListToMap( l_recNumMap, l_memBufList);
+ }
+ else // Add cache status for all MCSs for direct memory
+ {
+ TARGETING::TargetHandleList l_mcsList;
+ getChipletResources(l_mcsList,
+ TARGETING::TYPE_MCS,
+ TARGETING::UTIL_FILTER_ALL);
+ addListToMap( l_recNumMap, l_mcsList);
+ }
+
+ // check for any section that is invalid for all that share it
+ for (numRecValidMap_t::iterator itr = l_recNumMap.begin();
+ itr != l_recNumMap.end(); ++itr)
+ {
+ // The second.second is the accumulation of all pnorCacheValid
+ // bits. If true, then at least one target is using this
+ // VPD_REC_NUM section. Keep it.
+ if (itr->second.second)
+ {
+ TRACDCOMP( g_trac_vpd, "validateSharedPnorCache() "
+ "valid is %d for VPD_REC_NUM %d HUID %.8X "
+ "keep this section",
+ itr->second.second,
+ itr->first,
+ TARGETING::get_huid(itr->second.first));
+ }
+ // if false, then all that share this section, none are valid.
+ // Invalidate this section.
+ else
+ {
+ TRACFCOMP( g_trac_vpd, "validateSharedPnorCache() "
+ "valid is %d for VPD_REC_NUM %d HUID %.8X "
+ "invalidate this section",
+ itr->second.second,
+ itr->first,
+ TARGETING::get_huid(itr->second.first));
+
+ // invalidate cache section for this VPD_REC_NUM
+ errl = VPD::invalidatePnorCache(itr->second.first);
+ if (errl)
+ {
+ // Just commit the log and move on. No need to terminate IPL
+ errlCommit( errl, VPD_COMP_ID );
+ }
+ }
+ }
+ } while (0);
+
+ return errl;
+}
}; //end VPD namespace
OpenPOWER on IntegriCloud