From 9dee05c3d4c801d74972216a8c501e5c1c3fc2b6 Mon Sep 17 00:00:00 2001 From: whs Date: Mon, 14 Mar 2016 16:31:27 -0500 Subject: 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 Reviewed-by: Matthew A. Ploetz Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/22153 Tested-by: FSP CI Jenkins Reviewed-by: Daniel M. Crowell --- src/usr/vpd/dvpd.C | 15 ++++--- src/usr/vpd/pvpd.C | 18 ++++---- src/usr/vpd/vpd.C | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 146 insertions(+), 15 deletions(-) (limited to 'src/usr/vpd') 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(); + vpdSwitches.pnorCacheValid = 0; + i_target->setAttr( 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(); + vpdSwitches.pnorCacheValid = 0; + i_target->setAttr( 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 // ---------------------------------------------- // Trace - defined in vpd_common @@ -833,5 +834,132 @@ errlHndl_t invalidateAllPnorCaches ( bool i_setHwOnly ) return l_err; } +typedef std::pair targetValidPair_t; +typedef std::map 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_SWITCHES_type l_switches = + l_pTarg->getAttr(); + + 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 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 -- cgit v1.2.1