diff options
| author | Christian Geddes <crgeddes@us.ibm.com> | 2019-07-03 15:37:35 -0500 |
|---|---|---|
| committer | Daniel M Crowell <dcrowell@us.ibm.com> | 2019-07-17 15:16:41 -0500 |
| commit | 73acf956a1b5a8e3e22570ba927c6f89e8ad74f0 (patch) | |
| tree | 4fb7aee59519b114bf3d868f95ee5d739363c5b4 /src/usr/i2c/runtime | |
| parent | e7f8781ee64c8758890e58967cc13532c3c477a8 (diff) | |
| download | talos-hostboot-73acf956a1b5a8e3e22570ba927c6f89e8ad74f0.tar.gz talos-hostboot-73acf956a1b5a8e3e22570ba927c6f89e8ad74f0.zip | |
Support reading from EECACHE during runtime
To support VPD accesses at runtime we had to add support to access
the information in the EECACHE section of pnor during runtime. To
do this we copy the contents of the EECACHE section into reserved
memory during the runtime setup steps of hostboot. Then when HBRT
is loaded we will process that EECACHE section and built up a map
that will allow read/write accesses to the eecache section just
like during the IPL.
Change-Id: I2d08c883e6c09c3194d85abe141c35bb2b76b126
RTC: 204341
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/79985
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Matt Derksen <mderkse1@us.ibm.com>
Reviewed-by: Glenn Miles <milesg@ibm.com>
Reviewed-by: Daniel M Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/usr/i2c/runtime')
| -rw-r--r-- | src/usr/i2c/runtime/makefile | 6 | ||||
| -rw-r--r-- | src/usr/i2c/runtime/rt_eepromCache.C | 285 |
2 files changed, 288 insertions, 3 deletions
diff --git a/src/usr/i2c/runtime/makefile b/src/usr/i2c/runtime/makefile index e6bf9330b..73d3d464b 100644 --- a/src/usr/i2c/runtime/makefile +++ b/src/usr/i2c/runtime/makefile @@ -1,11 +1,11 @@ # IBM_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # -# $Source: src/usr/vpd/runtime/makefile $ +# $Source: src/usr/i2c/runtime/makefile $ # # OpenPOWER HostBoot Project # -# Contributors Listed Below - COPYRIGHT 2013,2015 +# Contributors Listed Below - COPYRIGHT 2013,2019 # [+] International Business Machines Corp. # # @@ -32,7 +32,7 @@ include ../i2c.mk #add unique object modules OBJS += rt_i2c.o - +OBJS += $(if $(CONFIG_SUPPORT_EEPROM_CACHING),rt_eepromCache.o) VPATH += .. include $(ROOTPATH)/config.mk diff --git a/src/usr/i2c/runtime/rt_eepromCache.C b/src/usr/i2c/runtime/rt_eepromCache.C new file mode 100644 index 000000000..e3b757b03 --- /dev/null +++ b/src/usr/i2c/runtime/rt_eepromCache.C @@ -0,0 +1,285 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/i2c/runtime/rt_eepromCache.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2019 */ +/* [+] 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 */ +/** + * @file rt_eepromCache.C + * + * @brief Runtime functionality of the eeprom cache driver + * + */ + +// ---------------------------------------------- +// Includes +// ---------------------------------------------- + +#include <errl/errlentry.H> +#include <devicefw/driverif.H> +#include <i2c/eepromddreasoncodes.H> +#include <runtime/interface.h> +#include <runtime/rt_targeting.H> +#include <targeting/common/utilFilter.H> +#include <targeting/attrrp.H> +#include <trace/interface.H> +#include <util/runtime/util_rt.H> +#include <sys/internode.h> +#include <errl/errlentry.H> +#include <errl/errlmanager.H> + +#include "../eepromCache.H" + +// ---------------------------------------------- +// Trace definitions +// ---------------------------------------------- +extern trace_desc_t* g_trac_eeprom; + +//#define TRACSSCOMP(args...) TRACFCOMP(args) +#define TRACSSCOMP(args...) + +namespace EEPROM +{ + +// Any time we access either any of the global variables defined above we want +// to wrap the call in this mutex to avoid multi-threading issues +mutex_t g_eecacheMutex = MUTEX_INITIALIZER; + +uint64_t g_eecachePnorVaddr[MAX_NODES_PER_SYS] = {0,0,0,0,0,0,0,0}; +std::map<eepromRecordHeader, EeepromEntryMetaData_t> g_cachedEeproms[MAX_NODES_PER_SYS]; + +// ------------------------------------------------------------------ +// rtEecacheInit +// ------------------------------------------------------------------ +struct rtEecacheInit +{ + rtEecacheInit() + { + errlHndl_t l_errl = nullptr; + + // Add cache status for the node + TARGETING::TargetHandleList l_nodeList; + getEncResources(l_nodeList, + TARGETING::TYPE_NODE, + TARGETING::UTIL_FILTER_ALL); + // Find all the targets with VPD switches + for (auto & l_node : l_nodeList) + { + uint8_t l_instance = TARGETING::AttrRP::getNodeId(l_node); + uint64_t vpd_size = 0; + eecacheSectionHeader* l_sectionHeader = + reinterpret_cast<eecacheSectionHeader*>( + hb_get_rt_rsvd_mem(Util::HBRT_MEM_LABEL_VPD, + l_instance, vpd_size)); + + g_eecachePnorVaddr[l_instance] = reinterpret_cast<uint64_t>(l_sectionHeader); + + // Check if reserved memory does not exist for this instance + if ((NULL == l_sectionHeader) || (0 == vpd_size)) + { + TRACFCOMP(g_trac_eeprom, + "rtEecacheInit(): ERROR Could not find VPD section of reserved memory for Node %d, ", + l_instance); + /*@ + * @errortype ERRL_SEV_UNRECOVERABLE + * @moduleid EEPROM_CACHE_INIT_RT + * @reasoncode EEPROM_CACHE_NO_VPD_IN_RSV_MEM + * @userdata1 Node Id + * @userdata2 Unused + * + * @devdesc Attempted to lookup VPD in reserved memory + * and failed + * @custdesc A problem occurred during the IPL of the + * system. + */ + l_errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + EEPROM::EEPROM_CACHE_INIT_RT, + EEPROM::EEPROM_CACHE_NO_VPD_IN_RSV_MEM, + l_instance, + 0, + ERRORLOG::ErrlEntry::ADD_SW_CALLOUT); + + errlCommit (l_errl, EEPROM_COMP_ID); + break; + + } + + eepromRecordHeader * l_recordHeaderToCopy = nullptr; + uint8_t l_eepromCount = 0; + for(int8_t i = 0; i < MAX_EEPROMS_VERSION_1; i++) + { + // Keep track of current record so we can use outside for loop + l_recordHeaderToCopy = &l_sectionHeader->recordHeaders[i]; + + // If internal_offset is UNSET_INTERNAL_OFFSET_VALUE then we will assume this address not been filled + if(l_recordHeaderToCopy->completeRecord.internal_offset != UNSET_INTERNAL_OFFSET_VALUE) + { + l_eepromCount++; + // Will return true if already found an entry in the list + if(addEepromToCachedList(*l_recordHeaderToCopy, + reinterpret_cast<uint64_t>(l_recordHeaderToCopy), + l_instance)) + { + + TRACFCOMP(g_trac_eeprom, + "rtEecacheInit(): ERROR Duplicate cache entries found in VPD reserved memory section"); + /*@ + * @errortype ERRL_SEV_UNRECOVERABLE + * @moduleid EEPROM_CACHE_INIT_RT + * @reasoncode EEPROM_DUPLICATE_CACHE_ENTRY + * @userdata1[0:31] i2c_master_huid + * @userdata1[32:39] port on i2c master eeprom slave is on + * @userdata1[40:47] engine on i2c master eeprom slave is on + * @userdata1[48:55] devAddr of eeprom slave + * @userdata1[56:63] muxSelect of eeprom slave (0xFF is not valid) + * @userdata2[0:31] size of eeprom + * @userdata2[32:63] Node Id + * @devdesc Attempted to lookup VPD in reserved memory + * and failed + * @custdesc A problem occurred during the IPL of the + * system. + */ + l_errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + EEPROM::EEPROM_CACHE_INIT_RT, + EEPROM::EEPROM_DUPLICATE_CACHE_ENTRY, + TWO_UINT32_TO_UINT64( + l_recordHeaderToCopy->completeRecord.i2c_master_huid, + TWO_UINT16_TO_UINT32( + TWO_UINT8_TO_UINT16( + l_recordHeaderToCopy->completeRecord.port, + l_recordHeaderToCopy->completeRecord.engine), + TWO_UINT8_TO_UINT16( + l_recordHeaderToCopy->completeRecord.devAddr, + l_recordHeaderToCopy->completeRecord.mux_select))), + TWO_UINT32_TO_UINT64(l_recordHeaderToCopy->completeRecord.cache_copy_size, + TO_UINT32(l_instance)), + ERRORLOG::ErrlEntry::ADD_SW_CALLOUT); + + errlCommit (l_errl, EEPROM_COMP_ID); + // Something is wrong so we have committed the unrecoverable + // but keep processing the eeproms because we want a full picture + // of what we understand the eeprom cache contents to be + continue; + } + } + } + + TRACFCOMP(g_trac_eeprom, "Found %d cached eeproms in reserved memory for node %d", + l_eepromCount, l_instance); + + printCurrentCachedEepromMap(); + + } + } + +}; +rtEecacheInit g_rtEecacheInit; + +void printCurrentCachedEepromMap(void) +{ + TRACFCOMP( g_trac_eeprom, + "printCurrentCachedEepromMap():"); + + mutex_lock(&g_eecacheMutex); + for(int8_t i = 0; i < MAX_NODES_PER_SYS; i++) + { + for(std::map<eepromRecordHeader, EeepromEntryMetaData_t>::iterator iter = g_cachedEeproms[i].begin(); + iter != g_cachedEeproms[i].end(); + ++iter) + { + TRACSSCOMP( g_trac_eeprom, + "printTableOfContents(): I2CM Huid: 0x%.08X, Port: 0x%.02X," + " Engine: 0x%.02X, Dev Addr: 0x%.02X," + " Mux Select: 0x%.02X, Size: 0x%.08X", + iter->first.completeRecord.i2c_master_huid, + iter->first.completeRecord.port, + iter->first.completeRecord.engine, + iter->first.completeRecord.devAddr, + iter->first.completeRecord.mux_select, + iter->first.completeRecord.cache_copy_size); + + TRACSSCOMP( g_trac_eeprom, + " " + "Internal Offset: 0x%.08X, Cache Valid: 0x%.02X", + iter->first.completeRecord.internal_offset, + iter->first.completeRecord.cached_copy_valid); + } + } + mutex_unlock(&g_eecacheMutex); + +} + +uint64_t lookupEepromCacheAddr(const eepromRecordHeader& i_eepromRecordHeader, + const uint8_t i_instance) +{ + uint64_t l_vaddr = 0; + std::map<eepromRecordHeader, EeepromEntryMetaData_t>::iterator l_it; + + // Wrap lookup in mutex because reads are not thread safe + mutex_lock(&g_eecacheMutex); + l_it = g_cachedEeproms[i_instance].find(i_eepromRecordHeader); + + if(l_it != g_cachedEeproms[i_instance].end()) + { + l_vaddr = l_it->second.cache_entry_address; + } + mutex_unlock(&g_eecacheMutex); + return l_vaddr; +} + +bool addEepromToCachedList(const eepromRecordHeader & i_eepromRecordHeader, + const uint64_t i_recordHeaderVaddr, + const uint8_t i_instance) +{ + bool l_matchFound = true; + + // Map accesses are not thread safe, make sure this is always wrapped in mutex + mutex_lock(&g_eecacheMutex); + + if(g_cachedEeproms[i_instance].find(i_eepromRecordHeader) == + g_cachedEeproms[i_instance].end()) + { + g_cachedEeproms[i_instance][i_eepromRecordHeader].cache_entry_address = + g_eecachePnorVaddr[i_instance] + i_eepromRecordHeader.completeRecord.internal_offset; + + g_cachedEeproms[i_instance][i_eepromRecordHeader].header_entry_address = + i_recordHeaderVaddr; + + TRACSSCOMP( g_trac_eeprom, + "addEepromToCachedList() Adding I2CM Huid: 0x%.08X, Port: 0x%.02X," + " Engine: 0x%.02X, Dev Addr: 0x%.02X, Mux Select: 0x%.02X," + " Size: 0x%.08X to g_cachedEeproms", + i_eepromRecordHeader.completeRecord.i2c_master_huid, + i_eepromRecordHeader.completeRecord.port, + i_eepromRecordHeader.completeRecord.engine, + i_eepromRecordHeader.completeRecord.devAddr, + i_eepromRecordHeader.completeRecord.mux_select, + i_eepromRecordHeader.completeRecord.cache_copy_size); + + l_matchFound = false; + } + + mutex_unlock(&g_eecacheMutex); + + return l_matchFound; +} + +} // end namespace EEPROM |

