diff options
Diffstat (limited to 'src/usr/vpd/vpd.C')
-rwxr-xr-x[-rw-r--r--] | src/usr/vpd/vpd.C | 287 |
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 |