summaryrefslogtreecommitdiffstats
path: root/src/usr/vpd/vpd.C
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr/vpd/vpd.C')
-rwxr-xr-x[-rw-r--r--]src/usr/vpd/vpd.C287
1 files changed, 286 insertions, 1 deletions
diff --git a/src/usr/vpd/vpd.C b/src/usr/vpd/vpd.C
index 64fa99f3f..cb08625cc 100644..100755
--- a/src/usr/vpd/vpd.C
+++ b/src/usr/vpd/vpd.C
@@ -5,7 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* COPYRIGHT International Business Machines Corp. 2013,2014 */
+/* Contributors Listed Below - COPYRIGHT 2013,2014 */
+/* [+] 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. */
@@ -26,7 +28,12 @@
#include <errl/errludtarget.H>
#include <vpd/vpdreasoncodes.H>
#include <initservice/initserviceif.H>
+#include <devicefw/driverif.H>
+#include <sys/mm.h>
#include "vpd.H"
+#include "mvpd.H"
+#include "cvpd.H"
+#include "spd.H"
// ----------------------------------------------
// Trace definitions
@@ -238,6 +245,31 @@ errlHndl_t writePNOR ( uint64_t i_byteAddr,
memcpy( (void*)(writeAddr),
i_data,
i_numBytes );
+
+ // @todo RTC:117042 - enable flush once PNOR writes supported
+ // Flush the page to make sure it gets to the PNOR
+#if 0
+ int rc = mm_remove_pages( FLUSH, (void*)addr, i_numBytes );
+ if( rc )
+ {
+ TRACFCOMP(g_trac_vpd,ERR_MRK"writePNOR() Error from mm_remove_pages, rc=%d",rc);
+ /*@
+ * @errortype
+ * @moduleid VPD_WRITE_PNOR
+ * @reasoncode VPD_REMOVE_PAGES_FAIL
+ * @userdata1 Requested Address
+ * @userdata2 rc from mm_remove_pages
+ * @devdesc writePNOR mm_remove_pages FLUSH failed
+ */
+ err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ VPD_WRITE_PNOR,
+ VPD_REMOVE_PAGES_FAIL,
+ addr,
+ TO_UINT64(rc),
+ true /*Add HB Software Callout*/ );
+ }
+#endif
} while( 0 );
TRACSSCOMP( g_trac_vpd,
@@ -322,4 +354,257 @@ errlHndl_t sendMboxWriteMsg ( size_t i_numBytes,
}
+// ------------------------------------------------------------------
+// resolveVpdSource
+// ------------------------------------------------------------------
+bool resolveVpdSource( TARGETING::Target * i_target,
+ bool i_readFromPnorEnabled,
+ bool i_readFromHwEnabled,
+ vpdCmdTarget i_vpdCmdTarget,
+ vpdCmdTarget& o_vpdSource )
+{
+ bool badConfig = false;
+ o_vpdSource = VPD::INVALID_LOCATION;
+
+ if( i_vpdCmdTarget == VPD::PNOR )
+ {
+ if( i_readFromPnorEnabled )
+ {
+ o_vpdSource = VPD::PNOR;
+ }
+ else
+ {
+ badConfig = true;
+ TRACFCOMP(g_trac_vpd,"resolveVpdSource: VpdCmdTarget=PNOR but READ_FROM_PNOR is disabled");
+ }
+ }
+ else if( i_vpdCmdTarget == VPD::SEEPROM )
+ {
+ if( i_readFromHwEnabled )
+ {
+ o_vpdSource = VPD::SEEPROM;
+ }
+ else
+ {
+ badConfig = true;
+ TRACFCOMP(g_trac_vpd,"resolveVpdSource: VpdCmdTarget=SEEPROM but READ_FROM_HW is disabled");
+ }
+ }
+ else // i_vpdCmdTarget == VPD::AUTOSELECT
+ {
+ if( i_readFromPnorEnabled &&
+ i_readFromHwEnabled )
+ {
+ // PNOR needs to be loaded before we can use it
+ TARGETING::ATTR_VPD_SWITCHES_type vpdSwitches =
+ i_target->getAttr<TARGETING::ATTR_VPD_SWITCHES>();
+ if( vpdSwitches.pnorLoaded )
+ {
+ o_vpdSource = VPD::PNOR;
+ }
+ else
+ {
+ o_vpdSource = VPD::SEEPROM;
+ }
+ }
+ else if( i_readFromPnorEnabled )
+ {
+ o_vpdSource = VPD::PNOR;
+ }
+ else if( i_readFromHwEnabled )
+ {
+ o_vpdSource = VPD::SEEPROM;
+ }
+ else
+ {
+ badConfig = true;
+ TRACFCOMP(g_trac_vpd,"resolveVpdSource: READ_FROM_PNOR and READ_FROM_HW disabled");
+ }
+ }
+
+ return badConfig;
+}
+
+
+// ------------------------------------------------------------------
+// ensureCacheIsInSync
+// ------------------------------------------------------------------
+errlHndl_t ensureCacheIsInSync ( TARGETING::Target * i_target )
+{
+ errlHndl_t l_err = NULL;
+
+ TRACSSCOMP( g_trac_vpd, ENTER_MRK"ensureCacheIsInSync() " );
+
+ IpVpdFacade& l_ipvpd = Singleton<MvpdFacade>::instance();
+
+ vpdRecord l_record = 0;
+ vpdKeyword l_keywordPN = 0;
+ vpdKeyword l_keywordSN = 0;
+
+ TARGETING::TYPE l_type = i_target->getAttr<TARGETING::ATTR_TYPE>();
+
+ if( l_type == TARGETING::TYPE_PROC )
+ {
+ l_record = MVPD::VINI;
+ l_keywordPN = MVPD::PN;
+ l_keywordSN = MVPD::SN;
+ }
+ else if( l_type == TARGETING::TYPE_MEMBUF )
+ {
+ l_ipvpd = Singleton<CvpdFacade>::instance();
+ l_record = CVPD::VINI;
+ l_keywordPN = CVPD::PN;
+ l_keywordSN = CVPD::SN;
+ }
+ else if( l_type == TARGETING::TYPE_DIMM )
+ {
+ // SPD does not have a singleton instance
+ // SPD does not use records
+ l_keywordPN = SPD::MODULE_PART_NUMBER;
+ l_keywordSN = SPD::MODULE_SERIAL_NUMBER;
+ }
+ else
+ {
+ TRACFCOMP(g_trac_vpd,ERR_MRK"ensureCacheIsInSync() Unexpected target type, huid=0x%X",TARGETING::get_huid(i_target));
+ /*@
+ * @errortype
+ * @moduleid VPD_ENSURE_CACHE_IS_IN_SYNC
+ * @reasoncode VPD_UNEXPECTED_TARGET_TYPE
+ * @userdata1 Target HUID
+ * @userdata2 <UNUSED>
+ * @devdesc Unexpected target type
+ */
+ l_err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ VPD_ENSURE_CACHE_IS_IN_SYNC,
+ VPD_UNEXPECTED_TARGET_TYPE,
+ TO_UINT64(TARGETING::get_huid(i_target)),
+ 0x0,
+ true /*Add HB Software Callout*/ );
+ return l_err;
+ }
+
+ do
+ {
+ // Compare the Part Numbers in PNOR/SEEPROM
+ bool l_matchPN = false;
+ if( ( l_type == TARGETING::TYPE_PROC ) ||
+ ( l_type == TARGETING::TYPE_MEMBUF ) )
+ {
+ l_err = l_ipvpd.cmpPnorToSeeprom( i_target,
+ l_record,
+ l_keywordPN,
+ l_matchPN );
+ }
+ else if( l_type == TARGETING::TYPE_DIMM )
+ {
+ l_err = SPD::cmpPnorToSeeprom( i_target,
+ l_keywordPN,
+ l_matchPN );
+ }
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_vpd,ERR_MRK"VPD::ensureCacheIsInSync: Error checking for PNOR/SEEPROM PN match");
+ break;
+ }
+
+ // Compare the Serial Numbers in PNOR/SEEPROM
+ bool l_matchSN = false;
+ if( ( l_type == TARGETING::TYPE_PROC ) ||
+ ( l_type == TARGETING::TYPE_MEMBUF ) )
+ {
+ l_err = l_ipvpd.cmpPnorToSeeprom( i_target,
+ l_record,
+ l_keywordSN,
+ l_matchSN );
+ }
+ else if( l_type == TARGETING::TYPE_DIMM )
+ {
+ l_err = SPD::cmpPnorToSeeprom( i_target,
+ l_keywordSN,
+ l_matchSN );
+ }
+ if( l_err )
+ {
+ TRACFCOMP(g_trac_vpd,ERR_MRK"VPD::ensureCacheIsInSync: Error checking for PNOR/SEEPROM SN match");
+ break;
+ }
+
+ // If we did not match, we need to load SEEPROM VPD data into PNOR
+ if( l_matchPN && l_matchSN )
+ {
+ TRACFCOMP(g_trac_vpd,"VPD::ensureCacheIsInSync: PNOR_PN/SN = SEEPROM_PN/SN");
+ }
+ else
+ {
+ TRACFCOMP(g_trac_vpd,"VPD::ensureCacheIsInSync: PNOR_PN/SN != SEEPROM_PN/SN, Loading PNOR from SEEPROM");
+
+ // @todo RTC 116553 - Need HCDB update call here
+ // Load the PNOR data from the SEEPROM
+ if( ( l_type == TARGETING::TYPE_PROC ) ||
+ ( l_type == TARGETING::TYPE_MEMBUF ) )
+ {
+ l_err = l_ipvpd.loadPnor( i_target );
+ }
+ else if( l_type == TARGETING::TYPE_DIMM )
+ {
+ l_err = SPD::loadPnor( i_target );
+ }
+ if( l_err )
+ {
+ TRACFCOMP(g_trac_vpd,"Error loading SEEPROM VPD into PNOR");
+ break;
+ }
+ }
+
+ // Set target attribute switch that says VPD is loaded into PNOR
+ TARGETING::ATTR_VPD_SWITCHES_type vpdSwitches =
+ i_target->getAttr<TARGETING::ATTR_VPD_SWITCHES>();
+ vpdSwitches.pnorLoaded = 1;
+ i_target->setAttr<TARGETING::ATTR_VPD_SWITCHES>( vpdSwitches );
+
+ } while(0);
+
+ TRACSSCOMP( g_trac_vpd, EXIT_MRK"ensureCacheIsInSync()" );
+
+ return l_err;
+}
+
+
+// ------------------------------------------------------------------
+// invalidatePnorCache
+// ------------------------------------------------------------------
+errlHndl_t invalidatePnorCache ( TARGETING::Target * i_target )
+{
+ errlHndl_t l_err = NULL;
+
+ TRACSSCOMP( g_trac_vpd, ENTER_MRK"invalidatePnorCache() " );
+
+ TARGETING::TYPE l_type = i_target->getAttr<TARGETING::ATTR_TYPE>();
+
+ if( l_type == TARGETING::TYPE_PROC )
+ {
+ l_err = Singleton<MvpdFacade>::instance().invalidatePnor( i_target );
+ }
+ else if( l_type == TARGETING::TYPE_MEMBUF )
+ {
+ l_err = Singleton<CvpdFacade>::instance().invalidatePnor( i_target );
+ }
+ else if( l_type == TARGETING::TYPE_DIMM )
+ {
+ l_err = SPD::invalidatePnor( i_target );
+ }
+
+ // Clear target attribute switch that says VPD is loaded into PNOR
+ TARGETING::ATTR_VPD_SWITCHES_type vpdSwitches =
+ i_target->getAttr<TARGETING::ATTR_VPD_SWITCHES>();
+ vpdSwitches.pnorLoaded = 0;
+ i_target->setAttr<TARGETING::ATTR_VPD_SWITCHES>( vpdSwitches );
+
+ TRACSSCOMP( g_trac_vpd, EXIT_MRK"invalidatePnorCache()" );
+
+ return l_err;
+}
+
+
}; //end VPD namespace
OpenPOWER on IntegriCloud