diff options
author | Bill Schwartz <whs@us.ibm.com> | 2015-02-27 15:41:10 -0600 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2015-05-21 18:00:20 -0500 |
commit | 56a2bf579633fec26b0b6afaec01314a15dddb9d (patch) | |
tree | ea9806eab8006f92437e13935a5bcb79c7cdb8a6 /src/usr/vpd/pvpd.C | |
parent | 9bd763dd507380adf58bd7d20d0c030706d6e979 (diff) | |
download | talos-hostboot-56a2bf579633fec26b0b6afaec01314a15dddb9d.tar.gz talos-hostboot-56a2bf579633fec26b0b6afaec01314a15dddb9d.zip |
Add support for backplane VPD
Replace the temporary use of mem buf to access planar vpd with new
planar vpd interfaces.
Change-Id: I24cda4d713806330a9f61d588006d63966f92550
RTC: 118373
Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/16326
Tested-by: Jenkins Server
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/usr/vpd/pvpd.C')
-rw-r--r-- | src/usr/vpd/pvpd.C | 369 |
1 files changed, 369 insertions, 0 deletions
diff --git a/src/usr/vpd/pvpd.C b/src/usr/vpd/pvpd.C new file mode 100644 index 000000000..ec6223709 --- /dev/null +++ b/src/usr/vpd/pvpd.C @@ -0,0 +1,369 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/vpd/pvpd.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2013,2015 */ +/* [+] 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. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +// ---------------------------------------------- +// Includes +// ---------------------------------------------- +#include <string.h> +#include <endian.h> +#include <trace/interface.H> +#include <errl/errlentry.H> +#include <errl/errlmanager.H> +#include <targeting/common/targetservice.H> +#include <targeting/common/util.H> +#include <targeting/common/utilFilter.H> +#include <devicefw/driverif.H> +#include <vfs/vfs.H> +#include <vpd/vpdreasoncodes.H> +#include <vpd/pvpdenums.H> +#include <vpd/vpd_if.H> +#include <i2c/eepromif.H> +#include <config.h> +#include "pvpd.H" +#include "cvpd.H" +#include "vpd.H" + +// ---------------------------------------------- +// Trace definitions +// ---------------------------------------------- +extern trace_desc_t* g_trac_vpd; + + +// ------------------------ +// Macros for unit testing +//#define TRACUCOMP(args...) TRACFCOMP(args) +#define TRACUCOMP(args...) +//#define TRACSSCOMP(args...) TRACFCOMP(args) +#define TRACSSCOMP(args...) + +namespace PVPD +{ + // ---------------------------------------------- + // Globals + // ---------------------------------------------- + mutex_t g_mutex = MUTEX_INITIALIZER; + + + /** + * @brief This function will perform the steps required to do a read from + * the Hostboot PVPD data. + * + * @param[in] i_opType - Operation Type - See DeviceFW::OperationType in + * driververif.H + * + * @param[in] i_target - Processor Target device + * + * @param [in/out] io_buffer - Pointer to the data that was read from + * the target device. This parameter, when set to NULL, will return + * the keyword size value in io_buflen. + * + * @param [in/out] io_buflen - Length of the buffer to be read or written + * to/from the target. This value should indicate the size of the + * io_buffer parameter that has been allocated. Being returned it + * will indicate the number of valid bytes in the buffer being + * returned. This parameter will contain the size of a keyword when + * the io_buffer parameter is passed in NULL. + * + * @param [in] i_accessType - Access Type - See DeviceFW::AccessType in + * usrif.H + * + * @param [in] i_args - This is an argument list for the device driver + * framework. + * + * @return errlHndl_t - NULL if successful, otherwise a pointer to the + * error log. + */ + errlHndl_t pvpdRead ( DeviceFW::OperationType i_opType, + TARGETING::Target * i_target, + void * io_buffer, + size_t & io_buflen, + int64_t i_accessType, + va_list i_args ) + { + errlHndl_t err = NULL; + IpVpdFacade::input_args_t args; + args.record = ((pvpdRecord)va_arg( i_args, uint64_t )); + args.keyword = ((pvpdKeyword)va_arg( i_args, uint64_t )); + args.location = ((VPD::vpdCmdTarget)va_arg( i_args, uint64_t )); + + TRACSSCOMP( g_trac_vpd, + ENTER_MRK"pvpdRead()" ); + + err = Singleton<PvpdFacade>::instance().read(i_target, + io_buffer, + io_buflen, + args); + + return err; + } + + + /** + * @brief This function will perform the steps required to do a write to + * the Hostboot PVPD data. + * + * @param[in] i_opType - Operation Type - See DeviceFW::OperationType in + * driververif.H + * + * @param[in] i_target - Processor Target device + * + * @param [in/out] io_buffer - Pointer to the data that was read from + * the target device. It will also be used to contain data to + * be written to the device. + * + * @param [in/out] io_buflen - Length of the buffer to be read or written + * to/from the target. This value should indicate the size of the + * io_buffer parameter that has been allocated. Being returned it + * will indicate the number of valid bytes in the buffer being + * returned. + * + * @param [in] i_accessType - Access Type - See DeviceFW::AccessType in + * usrif.H + * + * @param [in] i_args - This is an argument list for the device driver + * framework. + * + * @return errlHndl_t - NULL if successful, otherwise a pointer to the + * error log. + */ + errlHndl_t pvpdWrite ( DeviceFW::OperationType i_opType, + TARGETING::Target * i_target, + void * io_buffer, + size_t & io_buflen, + int64_t i_accessType, + va_list i_args ) + { + errlHndl_t err = NULL; + IpVpdFacade::input_args_t args; + args.record = ((pvpdRecord)va_arg( i_args, uint64_t )); + args.keyword = ((pvpdKeyword)va_arg( i_args, uint64_t )); + args.location = ((VPD::vpdCmdTarget)va_arg( i_args, uint64_t )); + + TRACSSCOMP( g_trac_vpd, + ENTER_MRK"pvpdWrite()" ); + + + err = Singleton<PvpdFacade>::instance().write(i_target, + io_buffer, + io_buflen, + args); + + return err; + } + + // Register with the routing code + DEVICE_REGISTER_ROUTE( DeviceFW::READ, + DeviceFW::PVPD, + TARGETING::TYPE_NODE, + pvpdRead ); + DEVICE_REGISTER_ROUTE( DeviceFW::WRITE, + DeviceFW::PVPD, + TARGETING::TYPE_NODE, + pvpdWrite ); + +}; // end namespace PVPD + +#if !defined(__HOSTBOOT_RUNTIME) +// -------------------------------------------------------- +// Presence Detection +//--------------------------------------------------------- + +/** + * @brief Performs a presence detect operation on a Node card. + * + * There is no FSI presence detection, just Planar vpd detection. + * Presence is always returned as Success (unless the unlikely case of too + * small of a buffer passed). A problem with planar EEPROM is logged but + * not passed up so that the enclosure and everything inside is not + * deconfigured. + * + * @param[in] i_opType Operation type, see DeviceFW::OperationType + * in driverif.H + * @param[in] i_target Presence detect target + * @param[in/out] io_buffer Read: Pointer to output data storage + * Write: Pointer to input data storage + * @param[in/out] io_buflen Input: size of io_buffer (in bytes, always 1) + * Output: Success = 1, Failure = 0 + * @param[in] i_accessType DeviceFW::AccessType enum (userif.H) + * @param[in] i_args This is an argument list for DD framework. + * In this function, there are no arguments. + * @return errlHndl_t + */ +errlHndl_t nodePresenceDetect(DeviceFW::OperationType i_opType, + TARGETING::Target* i_target, + void* io_buffer, + size_t& io_buflen, + int64_t i_accessType, + va_list i_args) +{ + errlHndl_t l_errl = NULL; + bool pvpd_present = true; + + if (unlikely(io_buflen < sizeof(bool))) + { + TRACFCOMP(g_trac_vpd, + ERR_MRK "nodePresenceDetect> Invalid data length: %d", + io_buflen); + /*@ + * @errortype + * @moduleid VPD::VPD_PVPD_PRESENCEDETECT + * @reasoncode VPD::VPD_INVALID_LENGTH + * @userdata1 Data Length + * @devdesc presenceDetect> Invalid data length (!= 1 bytes) + */ + l_errl = + new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + VPD::VPD_PVPD_PRESENCEDETECT, + VPD::VPD_INVALID_LENGTH, + TO_UINT64(io_buflen), + true /*SW error*/); + io_buflen = 0; + return l_errl; + } + +#if defined(CONFIG_PVPD_READ_FROM_HW) && defined(CONFIG_PVPD_READ_FROM_PNOR) + pvpd_present = VPD::pvpdPresent( i_target ); + if( pvpd_present ) + { + // Check if the VPD data in the PNOR matches the SEEPROM + l_errl = VPD::ensureCacheIsInSync( i_target ); + if( l_errl ) + { + TRACFCOMP(g_trac_vpd,ERR_MRK "nodePresenceDetect>" + " Error during ensureCacheIsInSync (PVPD)" ); + errlCommit( l_errl, FSI_COMP_ID ); + } + } + else + { + 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; + } +#endif + + // Always return presence. + // A returned error deconfigures the node and stops the IPL. + memcpy(io_buffer, &pvpd_present, sizeof(pvpd_present)); + io_buflen = sizeof(pvpd_present); + + return NULL; +} + +// Register as the presence detect for nodes. +DEVICE_REGISTER_ROUTE(DeviceFW::READ, + DeviceFW::PRESENT, + TARGETING::TYPE_NODE, + nodePresenceDetect); +#endif + +bool VPD::pvpdPresent( TARGETING::Target * i_target ) +{ + TRACSSCOMP( g_trac_vpd, ENTER_MRK"pvpdPresent()"); +#if(defined( CONFIG_PVPD_READ_FROM_HW ) && !defined( __HOSTBOOT_RUNTIME) ) + + return EEPROM::eepromPresence( i_target ); + +#else + return Singleton<PvpdFacade>::instance().hasVpdPresent( i_target, + PVPD::OPFR, + PVPD::VP ); +#endif +} + + +//PVPD Class Functions +/** + * @brief Constructor + * Planar VPD is included in the Centaur PNOR section. + * Including with Centaur vpd minimizes the number of PNOR sections. + */ +PvpdFacade::PvpdFacade() : +IpVpdFacade(CVPD::SECTION_SIZE, // note use of CVPD + CVPD::MAX_SECTIONS, // note use of CVPD + PVPD::pvpdRecords, + (sizeof(PVPD::pvpdRecords)/sizeof(PVPD::pvpdRecords[0])), + PVPD::pvpdKeywords, + (sizeof(PVPD::pvpdKeywords)/sizeof(PVPD::pvpdKeywords[0])), + PNOR::CENTAUR_VPD, // note use of CVPD + PVPD::g_mutex, + VPD::VPD_WRITE_PLANAR) +{ + TRACUCOMP(g_trac_vpd, "PvpdFacade::PvpdFacade> " ); + +#ifdef CONFIG_PVPD_READ_FROM_PNOR + iv_configInfo.vpdReadPNOR = true; +#else + iv_configInfo.vpdReadPNOR = false; +#endif +#ifdef CONFIG_PVPD_READ_FROM_HW + iv_configInfo.vpdReadHW = true; +#else + iv_configInfo.vpdReadHW = false; +#endif +#ifdef CONFIG_PVPD_WRITE_TO_PNOR + iv_configInfo.vpdWritePNOR = true; +#else + iv_configInfo.vpdWritePNOR = false; +#endif +#ifdef CONFIG_PVPD_WRITE_TO_HW + iv_configInfo.vpdWriteHW = true; +#else + iv_configInfo.vpdWriteHW = false; +#endif +} + +// Retrun lists of records that should be copied to pnor. +void PvpdFacade::getRecordLists( + const recordInfo* & o_primaryVpdRecords, + uint64_t & o_primaryRecSize, + const recordInfo* & o_altVpdRecords, + uint64_t & o_altRecSize) +{ + // Always return this object's list + o_primaryVpdRecords = iv_vpdRecords; + o_primaryRecSize = iv_recSize; + + // If the planar eeprom is being shared with a mem buf, + // then return the cvpd list as the alternative record list. + // At thip point, if the node is be processed, then the mem buffs + // might have not been discovered yet. If cvpd is being cached, then + // include the cvpd list as the altnative. +#ifdef CONFIG_CVPD_READ_FROM_PNOR + o_altVpdRecords = Singleton<CvpdFacade>::instance().iv_vpdRecords; + o_altRecSize = Singleton<CvpdFacade>::instance().iv_recSize; +#else + o_altVpdRecords = NULL; + o_altRecSize = 0; +#endif +} + |