summaryrefslogtreecommitdiffstats
path: root/src/usr/i2c
diff options
context:
space:
mode:
authorChristian Geddes <crgeddes@us.ibm.com>2019-07-03 15:37:35 -0500
committerDaniel M Crowell <dcrowell@us.ibm.com>2019-07-17 15:16:41 -0500
commit73acf956a1b5a8e3e22570ba927c6f89e8ad74f0 (patch)
tree4fb7aee59519b114bf3d868f95ee5d739363c5b4 /src/usr/i2c
parente7f8781ee64c8758890e58967cc13532c3c477a8 (diff)
downloadtalos-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')
-rw-r--r--src/usr/i2c/eepromCache.C588
-rw-r--r--src/usr/i2c/eepromCache.H106
-rw-r--r--src/usr/i2c/eepromCache_common.C326
-rwxr-xr-xsrc/usr/i2c/eepromdd.C55
-rw-r--r--src/usr/i2c/i2c.mk4
-rw-r--r--src/usr/i2c/makefile1
-rw-r--r--src/usr/i2c/runtime/makefile6
-rw-r--r--src/usr/i2c/runtime/rt_eepromCache.C285
8 files changed, 910 insertions, 461 deletions
diff --git a/src/usr/i2c/eepromCache.C b/src/usr/i2c/eepromCache.C
index 6993f35ee..b50f899bf 100644
--- a/src/usr/i2c/eepromCache.C
+++ b/src/usr/i2c/eepromCache.C
@@ -34,7 +34,7 @@
#include "i2c.H"
#include "eepromCache.H"
#include <i2c/i2cif.H>
-#include <i2c/eepromif.H>
+
#include <i2c/eepromddreasoncodes.H>
#include <initservice/initserviceif.H>
#include <initservice/initsvcreasoncodes.H>
@@ -55,6 +55,10 @@ extern trace_desc_t* g_trac_eeprom;
namespace EEPROM
{
+// Any time we access either any of the global variables defined below we want
+// to wrap the call in this mutex to avoid multi-threading issues
+mutex_t g_eecacheMutex = MUTEX_INITIALIZER;
+
// Global variable that will keep track of the virtual address which
// points to the start of the EECACHE section, and the size of this section.
// It is handy to keep these around so we do not need to look them up in the
@@ -70,287 +74,6 @@ uint64_t g_eecachePnorSize = 0;
// if this eeprom's hardware has changed this IPL
std::map<eepromRecordHeader, EeepromEntryMetaData_t> g_cachedEeproms;
-// 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 lookupEepromCacheAddr(const eepromRecordHeader& i_eepromRecordHeader)
-{
- 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.find(i_eepromRecordHeader);
- mutex_unlock(&g_eecacheMutex);
-
- if(l_it != g_cachedEeproms.end())
- {
- l_vaddr = l_it->second.cache_entry_address;
- }
- return l_vaddr;
-}
-
-uint64_t lookupEepromHeaderAddr(const eepromRecordHeader& i_eepromRecordHeader)
-{
- 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.find(i_eepromRecordHeader);
-
- if(l_it != g_cachedEeproms.end())
- {
- l_vaddr = l_it->second.header_entry_address;
- }
- mutex_unlock(&g_eecacheMutex);
-
- if(l_vaddr == 0)
- {
- TRACFCOMP( g_trac_eeprom,
- "lookupEepromHeaderAddr() failed to find"
- " I2CM Huid: 0x%.08X, Port: 0x%.02X,"
- " Engine: 0x%.02X, Dev Addr: 0x%.02X,"
- " Mux Select: 0x%.02X, Size: 0x%.08X"
- "in 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);
- }
- return l_vaddr;
-}
-
-errlHndl_t buildEepromRecordHeader(TARGETING::Target * i_target,
- eeprom_addr_t & io_eepromInfo,
- eepromRecordHeader & o_eepromRecordHeader)
-{
-
- TARGETING::Target * l_muxTarget = nullptr;
- TARGETING::Target * l_i2cMasterTarget = nullptr;
- TARGETING::TargetService& l_targetService = TARGETING::targetService();
- errlHndl_t l_errl = nullptr;
-
- do{
-
- l_errl = eepromReadAttributes(i_target, io_eepromInfo);
- if(l_errl)
- {
- TRACFCOMP( g_trac_eeprom,
- "buildEepromRecordHeader() error occured reading eeprom attributes for eepromType %d, target 0x%.08X, returning!!",
- io_eepromInfo.eepromRole,
- TARGETING::get_huid(i_target));
- l_errl->collectTrace(EEPROM_COMP_NAME);
- break;
- }
-
- // Grab the I2C mux target so we can read the HUID, if the target is NULL we will not be able
- // to lookup attribute to uniquely ID this eeprom so we will not cache it
- l_muxTarget = l_targetService.toTarget( io_eepromInfo.i2cMuxPath);
- if(l_muxTarget == nullptr)
- {
- TRACFCOMP( g_trac_eeprom,
- "buildEepromRecordHeader() Mux target associated with target 0x%.08X resolved to a nullptr , check attribute for eepromType %d. Skipping Cache",
- TARGETING::get_huid(i_target),
- io_eepromInfo.eepromRole);
- /*@
- * @errortype
- * @moduleid EEPROM_CACHE_EEPROM
- * @reasoncode EEPROM_I2C_MUX_PATH_ERROR
- * @userdata1 HUID of target we want to cache
- * @userdata2 Type of EEPROM we are caching
- * @devdesc buildEepromRecordHeader invalid mux target
- */
- l_errl = new ERRORLOG::ErrlEntry(
- ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- EEPROM_CACHE_EEPROM,
- EEPROM_I2C_MUX_PATH_ERROR,
- TARGETING::get_huid(i_target),
- io_eepromInfo.eepromRole,
- ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
- l_errl->collectTrace(EEPROM_COMP_NAME);
- break;
- }
-
- // Grab the I2C master target so we can read the HUID, if the target is NULL we will not be able
- // to lookup attribute to uniquely ID this eeprom so we will not cache it
- l_i2cMasterTarget = l_targetService.toTarget( io_eepromInfo.i2cMasterPath );
- if(l_i2cMasterTarget == nullptr)
- {
- TRACFCOMP( g_trac_eeprom,
- "buildEepromRecordHeader() I2C Master target associated with target 0x%.08X resolved to a nullptr , check attribute for eepromType %d. Skipping Cache ",
- TARGETING::get_huid(i_target),
- io_eepromInfo.eepromRole);
- /*@
- * @errortype
- * @moduleid EEPROM_CACHE_EEPROM
- * @reasoncode EEPROM_I2C_MASTER_PATH_ERROR
- * @userdata1 HUID of target we want to cache
- * @userdata2 Type of EEPROM we are caching
- * @devdesc buildEepromRecordHeader invalid master target
- */
- l_errl = new ERRORLOG::ErrlEntry(
- ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- EEPROM_CACHE_EEPROM,
- EEPROM_I2C_MASTER_PATH_ERROR,
- TARGETING::get_huid(i_target),
- io_eepromInfo.eepromRole,
- ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
- l_errl->collectTrace(EEPROM_COMP_NAME);
- break;
- }
-
- // This is what we will compare w/ when we are going through the existing
- // caches in the eeprom to see if we have already cached something
- // Or if no matches are found we will copy this into the header
- o_eepromRecordHeader.completeRecord.i2c_master_huid = l_i2cMasterTarget->getAttr<TARGETING::ATTR_HUID>();
- o_eepromRecordHeader.completeRecord.port = static_cast<uint8_t>(io_eepromInfo.port);
- o_eepromRecordHeader.completeRecord.engine = static_cast<uint8_t>(io_eepromInfo.engine);
- o_eepromRecordHeader.completeRecord.devAddr = static_cast<uint8_t>(io_eepromInfo.devAddr);
- o_eepromRecordHeader.completeRecord.mux_select = static_cast<uint8_t>(io_eepromInfo.i2cMuxBusSelector);
- o_eepromRecordHeader.completeRecord.cache_copy_size = static_cast<uint32_t>(io_eepromInfo.devSize_KB);
-
- // Do not set valid bit nor internal offset here as we do not have
- // enough information availible to determine
-
- }while(0);
-
- return l_errl;
-}
-
-// Do NOT allow adding/removing eeproms to cache during RT
-#ifndef __HOSTBOOT_RUNTIME
-
-void printTableOfContents(void)
-{
- eecacheSectionHeader * l_eecacheSectionHeaderPtr =
- reinterpret_cast<eecacheSectionHeader*>(g_eecachePnorVaddr);
-
- TRACFCOMP( g_trac_eeprom,
- "printTableOfContents(): Version = 0x%.02X"
- " End of Cache = 0x.08X",
- l_eecacheSectionHeaderPtr->version,
- l_eecacheSectionHeaderPtr->end_of_cache);
-
- for(uint8_t i = 0; i < MAX_EEPROMS_VERSION_1; i++)
- {
- eepromRecordHeader l_currentRecordHeader =
- l_eecacheSectionHeaderPtr->recordHeaders[i];
-
- if( l_currentRecordHeader.completeRecord.internal_offset !=
- UNSET_INTERNAL_OFFSET_VALUE)
- {
- TRACFCOMP( 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",
- l_currentRecordHeader.completeRecord.i2c_master_huid,
- l_currentRecordHeader.completeRecord.port,
- l_currentRecordHeader.completeRecord.engine,
- l_currentRecordHeader.completeRecord.devAddr,
- l_currentRecordHeader.completeRecord.mux_select,
- l_currentRecordHeader.completeRecord.cache_copy_size);
-
- TRACFCOMP( g_trac_eeprom,
- " "
- "Internal Offset: 0x%.08X, Cache Valid: 0x%.02X",
- l_currentRecordHeader.completeRecord.internal_offset,
- l_currentRecordHeader.completeRecord.cached_copy_valid);
- }
- }
-
-}
-
-/**
-*
-* @brief Lookup a given i_eepromRecordHeader in the global map of eeprom
-* caches and check if the eeprom has changed this IPL or not
-*
-* @param[in] i_eepromRecordHeader we want to look up
-*
-* @return bool Return TRUE if eeprom is found in map AND mark_target_changed
- was set to true for the eeprom entry. Return FALSE otherwise.
-*
-*/
-bool hasEeepromChanged(const eepromRecordHeader & i_eepromRecordHeader)
-{
- bool l_eepromHasChanged = false;
-
- // Map accesses are not thread safe, make sure this is always wrapped in mutex
- mutex_lock(&g_eecacheMutex);
-
- if(g_cachedEeproms.find(i_eepromRecordHeader) != g_cachedEeproms.end())
- {
- l_eepromHasChanged = g_cachedEeproms[i_eepromRecordHeader].mark_target_changed;
- }
-
- mutex_unlock(&g_eecacheMutex);
-
- return l_eepromHasChanged;
-}
-
-/**
-*
-* @brief Lookup a given i_eepromRecordHeader in the global map of eeprom
-* caches and mark that it has changed this IPL
-*
-* @param[in] i_eepromRecordHeader we want to mark as changed
-*
-* @return void
-*/
-void setEeepromChanged(const eepromRecordHeader & i_eepromRecordHeader)
-{
-
- // Map accesses are not thread safe, make sure this is always wrapped in mutex
- mutex_lock(&g_eecacheMutex);
-
- if(g_cachedEeproms.find(i_eepromRecordHeader) != g_cachedEeproms.end())
- {
- g_cachedEeproms[i_eepromRecordHeader].mark_target_changed = true;
- }
-
- mutex_unlock(&g_eecacheMutex);
-
-}
-
-bool addEepromToCachedList(const eepromRecordHeader & i_eepromRecordHeader,
- const uint64_t i_recordHeaderVaddr)
-{
- 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.find(i_eepromRecordHeader) == g_cachedEeproms.end())
- {
- g_cachedEeproms[i_eepromRecordHeader].cache_entry_address =
- g_eecachePnorVaddr + i_eepromRecordHeader.completeRecord.internal_offset;
-
- g_cachedEeproms[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;
-}
-
/**
* @brief Lookup I2C information for given eeprom, check if eeprom exists in cache.
* If it exists already determine if any updates are required. If it is not
@@ -1066,186 +789,163 @@ errlHndl_t setIsValidCacheEntry(const eepromRecordHeader& i_eepromRecordHeader,
return l_errl;
}
-#endif
-
-errlHndl_t eepromPerformOpCache(DeviceFW::OperationType i_opType,
- TARGETING::Target * i_target,
- void * io_buffer,
- size_t& io_buflen,
- eeprom_addr_t &i_eepromInfo)
+bool addEepromToCachedList(const eepromRecordHeader & i_eepromRecordHeader,
+ const uint64_t i_recordHeaderVaddr)
{
- errlHndl_t l_errl = nullptr;
- eepromRecordHeader l_eepromRecordHeader;
+ bool l_matchFound = true;
- do{
+ // Map accesses are not thread safe, make sure this is always wrapped in mutex
+ mutex_lock(&g_eecacheMutex);
+
+ if(g_cachedEeproms.find(i_eepromRecordHeader) == g_cachedEeproms.end())
+ {
+ g_cachedEeproms[i_eepromRecordHeader].cache_entry_address =
+ g_eecachePnorVaddr + i_eepromRecordHeader.completeRecord.internal_offset;
+
+ g_cachedEeproms[i_eepromRecordHeader].header_entry_address =
+ i_recordHeaderVaddr;
- TRACSSCOMP( g_trac_eeprom, ENTER_MRK"eepromPerformOpCache() "
- "Target HUID 0x%.08X Enter", TARGETING::get_huid(i_target));
+ 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_errl = buildEepromRecordHeader(i_target,
- i_eepromInfo,
- l_eepromRecordHeader);
+ l_matchFound = false;
+ }
- if(l_errl)
+ mutex_unlock(&g_eecacheMutex);
+
+ return l_matchFound;
+}
+
+void printTableOfContents(void)
+{
+ eecacheSectionHeader * l_eecacheSectionHeaderPtr =
+ reinterpret_cast<eecacheSectionHeader*>(g_eecachePnorVaddr);
+
+ TRACFCOMP( g_trac_eeprom,
+ "printTableOfContents(): Version = 0x%.02X"
+ " End of Cache = 0x.08X",
+ l_eecacheSectionHeaderPtr->version,
+ l_eecacheSectionHeaderPtr->end_of_cache);
+
+ for(uint8_t i = 0; i < MAX_EEPROMS_VERSION_1; i++)
+ {
+ eepromRecordHeader l_currentRecordHeader =
+ l_eecacheSectionHeaderPtr->recordHeaders[i];
+
+ if( l_currentRecordHeader.completeRecord.internal_offset !=
+ UNSET_INTERNAL_OFFSET_VALUE)
{
- // buildEepromRecordHeader should have traced any relavent information if
- // it was needed, just break out and pass the error along
- break;
+ TRACFCOMP( 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",
+ l_currentRecordHeader.completeRecord.i2c_master_huid,
+ l_currentRecordHeader.completeRecord.port,
+ l_currentRecordHeader.completeRecord.engine,
+ l_currentRecordHeader.completeRecord.devAddr,
+ l_currentRecordHeader.completeRecord.mux_select,
+ l_currentRecordHeader.completeRecord.cache_copy_size);
+
+ TRACFCOMP( g_trac_eeprom,
+ " "
+ "Internal Offset: 0x%.08X, Cache Valid: 0x%.02X",
+ l_currentRecordHeader.completeRecord.internal_offset,
+ l_currentRecordHeader.completeRecord.cached_copy_valid);
}
+ }
- uint64_t l_eepromCacheVaddr = lookupEepromCacheAddr(l_eepromRecordHeader);
+}
- // Ensure that a copy of the eeprom exists in our map of cached eeproms
- if(l_eepromCacheVaddr)
- {
- // First check if io_buffer is a nullptr, if so then assume user is
- // requesting size back in io_bufferlen
- if(io_buffer == nullptr)
- {
- io_buflen = l_eepromRecordHeader.completeRecord.cache_copy_size * KILOBYTE;
- TRACSSCOMP( g_trac_eeprom, "eepromPerformOpCache() "
- "io_buffer == nullptr , returning io_buflen as 0x%lx",
- io_buflen);
- break;
- }
+bool hasEeepromChanged(const eepromRecordHeader & i_eepromRecordHeader)
+{
+ bool l_eepromHasChanged = false;
- TRACSSCOMP( g_trac_eeprom, "eepromPerformOpCache() "
- "Performing %s on target 0x%.08X offset 0x%lx length 0x%x vaddr 0x%lx",
- (i_opType == DeviceFW::READ) ? "READ" : "WRITE",
- TARGETING::get_huid(i_target),
- i_eepromInfo.offset, io_buflen, l_eepromCacheVaddr);
+ // Map accesses are not thread safe, make sure this is always wrapped in mutex
+ mutex_lock(&g_eecacheMutex);
- // Make sure that offset + buflen are less than the total size of the eeprom
- if(i_eepromInfo.offset + io_buflen >
- (l_eepromRecordHeader.completeRecord.cache_copy_size * KILOBYTE))
- {
- TRACFCOMP(g_trac_eeprom,
- ERR_MRK"eepromPerformOpCache: i_eepromInfo.offset + i_offset is greater than size of eeprom (0x%x KB)",
- l_eepromRecordHeader.completeRecord.cache_copy_size);
- /*@
- * @errortype
- * @moduleid EEPROM_CACHE_PERFORM_OP
- * @reasoncode EEPROM_OVERFLOW_ERROR
- * @userdata1 Length of Operation
- * @userdata2 Offset we are attempting to read/write
- * @custdesc Soft error in Firmware
- * @devdesc cacheEeprom invalid op type
- */
- l_errl = new ERRORLOG::ErrlEntry(
- ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- EEPROM_CACHE_PERFORM_OP,
- EEPROM_OVERFLOW_ERROR,
- TO_UINT64(io_buflen),
- TO_UINT64(i_eepromInfo.offset),
- ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
- ERRORLOG::ErrlUserDetailsTarget(i_target).addToLog(l_errl);
- l_errl->collectTrace( EEPROM_COMP_NAME );
+ if(g_cachedEeproms.find(i_eepromRecordHeader) != g_cachedEeproms.end())
+ {
+ l_eepromHasChanged = g_cachedEeproms[i_eepromRecordHeader].mark_target_changed;
+ }
- break;
- }
+ mutex_unlock(&g_eecacheMutex);
- if(i_opType == DeviceFW::READ)
- {
- memcpy(io_buffer,
- reinterpret_cast<void *>(l_eepromCacheVaddr + i_eepromInfo.offset),
- io_buflen);
- }
- else if(i_opType == DeviceFW::WRITE)
- {
- memcpy(reinterpret_cast<void *>(l_eepromCacheVaddr + i_eepromInfo.offset),
- io_buffer,
- io_buflen);
+ return l_eepromHasChanged;
+}
- #ifndef __HOSTBOOT_RUNTIME
+void setEeepromChanged(const eepromRecordHeader & i_eepromRecordHeader)
+{
- // Perform flush to ensure pnor is updated
- int rc = mm_remove_pages( FLUSH,
- reinterpret_cast<void *>(l_eepromCacheVaddr + i_eepromInfo.offset),
- io_buflen );
- if( rc )
- {
- TRACFCOMP(g_trac_eeprom,
- ERR_MRK"eepromPerformOpCache: Error from mm_remove_pages trying for flush contents write to pnor! rc=%d",
- rc);
- /*@
- * @errortype
- * @moduleid EEPROM_CACHE_PERFORM_OP
- * @reasoncode EEPROM_FAILED_TO_FLUSH_CONTENTS
- * @userdata1 Requested Address
- * @userdata2 rc from mm_remove_pages
- * @devdesc cacheEeprom mm_remove_pages FLUSH failed
- */
- l_errl = new ERRORLOG::ErrlEntry(
- ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- EEPROM_CACHE_PERFORM_OP,
- EEPROM_FAILED_TO_FLUSH_CONTENTS,
- (l_eepromCacheVaddr + i_eepromInfo.offset),
- TO_UINT64(rc),
- ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
- l_errl->collectTrace( EEPROM_COMP_NAME );
- }
- #endif //__HOSTBOOT_RUNTIME
- }
- else
- {
- TRACFCOMP(g_trac_eeprom,
- ERR_MRK"eepromPerformOpCache: Invalid OP_TYPE passed to function, i_opType=%d",
- i_opType);
- /*@
- * @errortype
- * @moduleid EEPROM_CACHE_PERFORM_OP
- * @reasoncode EEPROM_INVALID_OPERATION
- * @userdata1[0:31] Op Type that was invalid
- * @userdata1[32:63] Eeprom Role
- * @userdata2 Offset we are attempting to perfrom op on
- * @custdesc Soft error in Firmware
- * @devdesc cacheEeprom invalid op type
- */
- l_errl = new ERRORLOG::ErrlEntry(
- ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- EEPROM_CACHE_PERFORM_OP,
- EEPROM_INVALID_OPERATION,
- TWO_UINT32_TO_UINT64(i_opType,
- i_eepromInfo.eepromRole),
- TO_UINT64(i_eepromInfo.offset),
- ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
- ERRORLOG::ErrlUserDetailsTarget(i_target).addToLog(l_errl);
- l_errl->collectTrace( EEPROM_COMP_NAME );
- }
- }
- else
- {
- TRACFCOMP( g_trac_eeprom,"eepromPerformOpCache: Failed to find entry in cache for 0x%.08X, %s failed",
- TARGETING::get_huid(i_target),
- (i_opType == DeviceFW::READ) ? "READ" : "WRITE");
- /*@
- * @errortype
- * @moduleid EEPROM_CACHE_PERFORM_OP
- * @reasoncode EEPROM_NOT_IN_CACHE
- * @userdata1[0:31] Op Type
- * @userdata1[32:63] Eeprom Role
- * @userdata2 Offset we are attempting to read/write
- * @custdesc Soft error in Firmware
- * @devdesc Tried to lookup eeprom not in cache
- */
- l_errl = new ERRORLOG::ErrlEntry(
- ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- EEPROM_CACHE_PERFORM_OP,
- EEPROM_NOT_IN_CACHE,
- TWO_UINT32_TO_UINT64(i_opType,
- i_eepromInfo.eepromRole),
- TO_UINT64(i_eepromInfo.offset),
- ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
- ERRORLOG::ErrlUserDetailsTarget(i_target).addToLog(l_errl);
- l_errl->collectTrace( EEPROM_COMP_NAME );
- }
+ // Map accesses are not thread safe, make sure this is always wrapped in mutex
+ mutex_lock(&g_eecacheMutex);
+
+ if(g_cachedEeproms.find(i_eepromRecordHeader) != g_cachedEeproms.end())
+ {
+ g_cachedEeproms[i_eepromRecordHeader].mark_target_changed = true;
+ }
- TRACSSCOMP( g_trac_eeprom, EXIT_MRK"eepromPerformOpCache() "
- "Target HUID 0x%.08X Exit", TARGETING::get_huid(i_target));
+ mutex_unlock(&g_eecacheMutex);
- }while(0);
+}
- return l_errl;
+uint64_t lookupEepromCacheAddr(const eepromRecordHeader& i_eepromRecordHeader)
+{
+ 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.find(i_eepromRecordHeader);
+
+ if(l_it != g_cachedEeproms.end())
+ {
+ l_vaddr = l_it->second.cache_entry_address;
+ }
+
+ mutex_unlock(&g_eecacheMutex);
+
+ return l_vaddr;
+}
+
+uint64_t lookupEepromHeaderAddr(const eepromRecordHeader& i_eepromRecordHeader)
+{
+ 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.find(i_eepromRecordHeader);
+
+ if(l_it != g_cachedEeproms.end())
+ {
+ l_vaddr = l_it->second.header_entry_address;
+ }
+ mutex_unlock(&g_eecacheMutex);
+
+ if(l_vaddr == 0)
+ {
+ TRACFCOMP( g_trac_eeprom,
+ "lookupEepromHeaderAddr() failed to find"
+ " I2CM Huid: 0x%.08X, Port: 0x%.02X,"
+ " Engine: 0x%.02X, Dev Addr: 0x%.02X,"
+ " Mux Select: 0x%.02X, Size: 0x%.08X"
+ "in 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);
+ }
+ return l_vaddr;
}
}
diff --git a/src/usr/i2c/eepromCache.H b/src/usr/i2c/eepromCache.H
index 9e0e140d8..253367b07 100644
--- a/src/usr/i2c/eepromCache.H
+++ b/src/usr/i2c/eepromCache.H
@@ -97,10 +97,29 @@ errlHndl_t buildEepromRecordHeader(TARGETING::Target * i_target,
eeprom_addr_t & io_eepromInfo,
eepromRecordHeader & o_eepromRecordHeader);
+
+#ifndef __HOSTBOOT_RUNTIME
+
+/**
+*
+* @brief Check if entry already exists in g_cachedEeproms, if a match is
+* found then return true. If there is no match, add it to the list
+* and return false;
+*
+* @param[in] i_eepromRecordHeader Header for record we want to add to map
+*
+* @param[in] i_recordHeaderVaddr Virtual address to PNOR copy of header information
+*
+* @return TRUE if entry is already in map FALSE if this is a new entry
+*
+*/
+bool addEepromToCachedList(const eepromRecordHeader & i_eepromRecordHeader,
+ const uint64_t i_recordHeaderVaddr);
+
/**
*
* @brief Perform a lookup on the global map g_cachedEeproms to get a
-* virtual address for a given EEPROM cache entry
+* virtual address for a given EEPROM entry in the EECACHE table of contents
*
* @param[in] i_eepromRecordHeader
*
@@ -110,12 +129,12 @@ errlHndl_t buildEepromRecordHeader(TARGETING::Target * i_target,
* @return uint64_t virtual address pointing to the cached eeprom data in pnor
*
*/
-uint64_t lookupEepromCacheAddr(const eepromRecordHeader& i_eepromRecordHeader);
+uint64_t lookupEepromHeaderAddr(const eepromRecordHeader& i_eepromRecordHeader);
/**
*
* @brief Perform a lookup on the global map g_cachedEeproms to get a
-* virtual address for a given EEPROM entry in the EECACHE table of contents
+* virtual address for a given EEPROM cache entry
*
* @param[in] i_eepromRecordHeader
*
@@ -125,9 +144,19 @@ uint64_t lookupEepromCacheAddr(const eepromRecordHeader& i_eepromRecordHeader);
* @return uint64_t virtual address pointing to the cached eeprom data in pnor
*
*/
-uint64_t lookupEepromHeaderAddr(const eepromRecordHeader& i_eepromRecordHeader);
+uint64_t lookupEepromCacheAddr(const eepromRecordHeader& i_eepromRecordHeader);
+
+
+/**
+*
+* @brief Print the info found in the Table of Contents of the EECACHE
+* section of pnor to trace buffer
+*
+* @return void
+*
+*/
+void printTableOfContents(void);
-#ifndef __HOSTBOOT_RUNTIME
/**
*
@@ -164,16 +193,77 @@ errlHndl_t setIsValidCacheEntry(const TARGETING::Target * i_target,
*
*/
errlHndl_t setIsValidCacheEntry(const eepromRecordHeader& i_eepromRecordHeader, bool i_isValid);
+
/**
*
-* @brief Print the info found in the Table of Contents of the EECACHE
-* section of pnor to trace buffer
+* @brief Lookup a given i_eepromRecordHeader in the global map of eeprom
+* caches and check if the eeprom has changed this IPL or not
+*
+* @param[in] i_eepromRecordHeader we want to look up
+*
+* @return bool Return TRUE if eeprom is found in map AND mark_target_changed
+ was set to true for the eeprom entry. Return FALSE otherwise.
+*
+*/
+bool hasEeepromChanged(const eepromRecordHeader & i_eepromRecordHeader);
+
+/**
+*
+* @brief Lookup a given i_eepromRecordHeader in the global map of eeprom
+* caches and mark that it has changed this IPL
+*
+* @param[in] i_eepromRecordHeader we want to mark as changed
*
* @return void
+*/
+void setEeepromChanged(const eepromRecordHeader & i_eepromRecordHeader);
+#else
+/**
+*
+* @brief Check if entry already exists in g_cachedEeproms, if a match is
+* found then return true. If there is no match, add it to the list
+* and return false;
+*
+* @param[in] i_eepromRecordHeader Header for record we want to add to map
+*
+* @param[in] i_recordHeaderVaddr Virtual address to PNOR copy of header information
+*
+* @param[in] i_instance Node ID that this eeprom is on
+*
+* @return TRUE if entry is already in map FALSE if this is a new entry
*
*/
-void printTableOfContents(void);
+bool addEepromToCachedList(const eepromRecordHeader & i_eepromRecordHeader,
+ const uint64_t i_recordHeaderVaddr,
+ const uint8_t i_instance);
+/**
+*
+* @brief Perform a lookup on the global map g_cachedEeproms to get a
+* virtual address for a given EEPROM cache entry
+*
+* @param[in] i_eepromRecordHeader Header for record we want to add to lookup address for
+*
+* @param[in] i_isntance Node ID that this eeprom is on
+*
+* @pre It is expected that i_eepromRecordHeader has valid information for
+* the uniqueID (i2cm_huid, port, engine, devAddr, mux_select)
+*
+* @return uint64_t virtual address pointing to the cached eeprom data in pnor
+*
+*/
+uint64_t lookupEepromCacheAddr(const eepromRecordHeader& i_eepromRecordHeader,
+ const uint8_t i_instance);
+
+/**
+*
+* @brief Walk through g_cachedEeproms map and print information about
+* the cached eeproms found
+*
+* @return void
+*
+*/
+void printCurrentCachedEepromMap(void);
#endif // __HOSTBOOT_RUNTIME
}
diff --git a/src/usr/i2c/eepromCache_common.C b/src/usr/i2c/eepromCache_common.C
new file mode 100644
index 000000000..c7a838294
--- /dev/null
+++ b/src/usr/i2c/eepromCache_common.C
@@ -0,0 +1,326 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/i2c/eepromCache_common.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 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 */
+#include "eepromCache.H"
+#include <errl/errlmanager.H>
+#include <i2c/eepromif.H>
+#include <i2c/eepromddreasoncodes.H>
+#include <errl/errludtarget.H>
+#include <config.h>
+
+#ifdef __HOSTBOOT_RUNTIME
+#include <targeting/attrrp.H>
+#else
+#include <sys/mm.h>
+#endif
+
+extern trace_desc_t* g_trac_eeprom;
+
+//#define TRACSSCOMP(args...) TRACFCOMP(args)
+#define TRACSSCOMP(args...)
+
+namespace EEPROM
+{
+
+errlHndl_t buildEepromRecordHeader(TARGETING::Target * i_target,
+ eeprom_addr_t & io_eepromInfo,
+ eepromRecordHeader & o_eepromRecordHeader)
+{
+
+ TARGETING::Target * l_muxTarget = nullptr;
+ TARGETING::Target * l_i2cMasterTarget = nullptr;
+ TARGETING::TargetService& l_targetService = TARGETING::targetService();
+ errlHndl_t l_errl = nullptr;
+
+ do{
+
+ l_errl = eepromReadAttributes(i_target, io_eepromInfo);
+ if(l_errl)
+ {
+ TRACFCOMP( g_trac_eeprom,
+ "buildEepromRecordHeader() error occurred reading eeprom attributes for eepromType %d, target 0x%.08X, returning!!",
+ io_eepromInfo.eepromRole,
+ TARGETING::get_huid(i_target));
+ l_errl->collectTrace(EEPROM_COMP_NAME);
+ break;
+ }
+
+ // Grab the I2C mux target so we can read the HUID, if the target is NULL we will not be able
+ // to lookup attribute to uniquely ID this eeprom so we will not cache it
+ l_muxTarget = l_targetService.toTarget( io_eepromInfo.i2cMuxPath);
+ if(l_muxTarget == nullptr)
+ {
+ TRACFCOMP( g_trac_eeprom,
+ "buildEepromRecordHeader() Mux target associated with target 0x%.08X resolved to a nullptr , check attribute for eepromType %d. Skipping Cache",
+ TARGETING::get_huid(i_target),
+ io_eepromInfo.eepromRole);
+ /*@
+ * @errortype
+ * @moduleid EEPROM_CACHE_EEPROM
+ * @reasoncode EEPROM_I2C_MUX_PATH_ERROR
+ * @userdata1 HUID of target we want to cache
+ * @userdata2 Type of EEPROM we are caching
+ * @devdesc buildEepromRecordHeader invalid mux target
+ */
+ l_errl = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ EEPROM_CACHE_EEPROM,
+ EEPROM_I2C_MUX_PATH_ERROR,
+ TARGETING::get_huid(i_target),
+ io_eepromInfo.eepromRole,
+ ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
+ l_errl->collectTrace(EEPROM_COMP_NAME);
+ break;
+ }
+
+ // Grab the I2C master target so we can read the HUID, if the target is NULL we will not be able
+ // to lookup attribute to uniquely ID this eeprom so we will not cache it
+ l_i2cMasterTarget = l_targetService.toTarget( io_eepromInfo.i2cMasterPath );
+ if(l_i2cMasterTarget == nullptr)
+ {
+ TRACFCOMP( g_trac_eeprom,
+ "buildEepromRecordHeader() I2C Master target associated with target 0x%.08X resolved to a nullptr , check attribute for eepromType %d. Skipping Cache ",
+ TARGETING::get_huid(i_target),
+ io_eepromInfo.eepromRole);
+ /*@
+ * @errortype
+ * @moduleid EEPROM_CACHE_EEPROM
+ * @reasoncode EEPROM_I2C_MASTER_PATH_ERROR
+ * @userdata1 HUID of target we want to cache
+ * @userdata2 Type of EEPROM we are caching
+ * @devdesc buildEepromRecordHeader invalid master target
+ */
+ l_errl = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ EEPROM_CACHE_EEPROM,
+ EEPROM_I2C_MASTER_PATH_ERROR,
+ TARGETING::get_huid(i_target),
+ io_eepromInfo.eepromRole,
+ ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
+ l_errl->collectTrace(EEPROM_COMP_NAME);
+ break;
+ }
+
+ // This is what we will compare w/ when we are going through the existing
+ // caches in the eeprom to see if we have already cached something
+ // Or if no matches are found we will copy this into the header
+ o_eepromRecordHeader.completeRecord.i2c_master_huid = l_i2cMasterTarget->getAttr<TARGETING::ATTR_HUID>();
+ o_eepromRecordHeader.completeRecord.port = static_cast<uint8_t>(io_eepromInfo.port);
+ o_eepromRecordHeader.completeRecord.engine = static_cast<uint8_t>(io_eepromInfo.engine);
+ o_eepromRecordHeader.completeRecord.devAddr = static_cast<uint8_t>(io_eepromInfo.devAddr);
+ o_eepromRecordHeader.completeRecord.mux_select = static_cast<uint8_t>(io_eepromInfo.i2cMuxBusSelector);
+ o_eepromRecordHeader.completeRecord.cache_copy_size = static_cast<uint32_t>(io_eepromInfo.devSize_KB);
+
+ // Do not set valid bit nor internal offset here as we do not have
+ // enough information availible to determine
+
+ }while(0);
+
+ return l_errl;
+}
+
+errlHndl_t eepromPerformOpCache(DeviceFW::OperationType i_opType,
+ TARGETING::Target * i_target,
+ void * io_buffer,
+ size_t& io_buflen,
+ eeprom_addr_t &i_eepromInfo)
+{
+ errlHndl_t l_errl = nullptr;
+ eepromRecordHeader l_eepromRecordHeader;
+
+ do{
+
+ TRACSSCOMP( g_trac_eeprom, ENTER_MRK"eepromPerformOpCache() "
+ "Target HUID 0x%.08X Enter", TARGETING::get_huid(i_target));
+
+ l_errl = buildEepromRecordHeader(i_target,
+ i_eepromInfo,
+ l_eepromRecordHeader);
+
+ if(l_errl)
+ {
+ // buildEepromRecordHeader should have traced any relavent information if
+ // it was needed, just break out and pass the error along
+ break;
+ }
+
+#ifndef __HOSTBOOT_RUNTIME
+ uint64_t l_eepromCacheVaddr = lookupEepromCacheAddr(l_eepromRecordHeader);
+#else
+ uint8_t l_instance = TARGETING::AttrRP::getNodeId(i_target);
+ uint64_t l_eepromCacheVaddr = lookupEepromCacheAddr(l_eepromRecordHeader, l_instance);
+#endif
+
+ // Ensure that a copy of the eeprom exists in our map of cached eeproms
+ if(l_eepromCacheVaddr)
+ {
+ // First check if io_buffer is a nullptr, if so then assume user is
+ // requesting size back in io_bufferlen
+ if(io_buffer == nullptr)
+ {
+ io_buflen = l_eepromRecordHeader.completeRecord.cache_copy_size * KILOBYTE;
+ TRACSSCOMP( g_trac_eeprom, "eepromPerformOpCache() "
+ "io_buffer == nullptr , returning io_buflen as 0x%lx",
+ io_buflen);
+ break;
+ }
+
+ TRACSSCOMP( g_trac_eeprom, "eepromPerformOpCache() "
+ "Performing %s on target 0x%.08X offset 0x%lx length 0x%x vaddr 0x%lx",
+ (i_opType == DeviceFW::READ) ? "READ" : "WRITE",
+ TARGETING::get_huid(i_target),
+ i_eepromInfo.offset, io_buflen, l_eepromCacheVaddr);
+
+ // Make sure that offset + buflen are less than the total size of the eeprom
+ if(i_eepromInfo.offset + io_buflen >
+ (l_eepromRecordHeader.completeRecord.cache_copy_size * KILOBYTE))
+ {
+ TRACFCOMP(g_trac_eeprom,
+ ERR_MRK"eepromPerformOpCache: i_eepromInfo.offset + i_offset is greater than size of eeprom (0x%x KB)",
+ l_eepromRecordHeader.completeRecord.cache_copy_size);
+ /*@
+ * @errortype
+ * @moduleid EEPROM_CACHE_PERFORM_OP
+ * @reasoncode EEPROM_OVERFLOW_ERROR
+ * @userdata1 Length of Operation
+ * @userdata2 Offset we are attempting to read/write
+ * @custdesc Soft error in Firmware
+ * @devdesc cacheEeprom invalid op type
+ */
+ l_errl = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ EEPROM_CACHE_PERFORM_OP,
+ EEPROM_OVERFLOW_ERROR,
+ TO_UINT64(io_buflen),
+ TO_UINT64(i_eepromInfo.offset),
+ ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
+ ERRORLOG::ErrlUserDetailsTarget(i_target).addToLog(l_errl);
+ l_errl->collectTrace( EEPROM_COMP_NAME );
+
+ break;
+ }
+
+ if(i_opType == DeviceFW::READ)
+ {
+ memcpy(io_buffer,
+ reinterpret_cast<void *>(l_eepromCacheVaddr + i_eepromInfo.offset),
+ io_buflen);
+ }
+ else if(i_opType == DeviceFW::WRITE)
+ {
+ memcpy(reinterpret_cast<void *>(l_eepromCacheVaddr + i_eepromInfo.offset),
+ io_buffer,
+ io_buflen);
+
+#ifndef __HOSTBOOT_RUNTIME
+ // Perform flush to ensure pnor is updated
+ int rc = mm_remove_pages( FLUSH,
+ reinterpret_cast<void *>(l_eepromCacheVaddr + i_eepromInfo.offset),
+ io_buflen );
+ if( rc )
+ {
+ TRACFCOMP(g_trac_eeprom,
+ ERR_MRK"eepromPerformOpCache: Error from mm_remove_pages trying for flush contents write to pnor! rc=%d",
+ rc);
+ /*@
+ * @errortype
+ * @moduleid EEPROM_CACHE_PERFORM_OP
+ * @reasoncode EEPROM_FAILED_TO_FLUSH_CONTENTS
+ * @userdata1 Requested Address
+ * @userdata2 rc from mm_remove_pages
+ * @devdesc cacheEeprom mm_remove_pages FLUSH failed
+ */
+ l_errl = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ EEPROM_CACHE_PERFORM_OP,
+ EEPROM_FAILED_TO_FLUSH_CONTENTS,
+ (l_eepromCacheVaddr + i_eepromInfo.offset),
+ TO_UINT64(rc),
+ ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
+ l_errl->collectTrace( EEPROM_COMP_NAME );
+ }
+#endif
+ }
+ else
+ {
+ TRACFCOMP(g_trac_eeprom,
+ ERR_MRK"eepromPerformOpCache: Invalid OP_TYPE passed to function, i_opType=%d",
+ i_opType);
+ /*@
+ * @errortype
+ * @moduleid EEPROM_CACHE_PERFORM_OP
+ * @reasoncode EEPROM_INVALID_OPERATION
+ * @userdata1[0:31] Op Type that was invalid
+ * @userdata1[32:63] Eeprom Role
+ * @userdata2 Offset we are attempting to perfrom op on
+ * @custdesc Soft error in Firmware
+ * @devdesc cacheEeprom invalid op type
+ */
+ l_errl = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ EEPROM_CACHE_PERFORM_OP,
+ EEPROM_INVALID_OPERATION,
+ TWO_UINT32_TO_UINT64(i_opType,
+ i_eepromInfo.eepromRole),
+ TO_UINT64(i_eepromInfo.offset),
+ ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
+ ERRORLOG::ErrlUserDetailsTarget(i_target).addToLog(l_errl);
+ l_errl->collectTrace( EEPROM_COMP_NAME );
+ }
+ }
+ else
+ {
+ TRACFCOMP( g_trac_eeprom,"eepromPerformOpCache: Failed to find entry in cache for 0x%.08X, %s failed",
+ TARGETING::get_huid(i_target),
+ (i_opType == DeviceFW::READ) ? "READ" : "WRITE");
+ /*@
+ * @errortype
+ * @moduleid EEPROM_CACHE_PERFORM_OP
+ * @reasoncode EEPROM_NOT_IN_CACHE
+ * @userdata1[0:31] Op Type
+ * @userdata1[32:63] Eeprom Role
+ * @userdata2 Offset we are attempting to read/write
+ * @custdesc Soft error in Firmware
+ * @devdesc Tried to lookup eeprom not in cache
+ */
+ l_errl = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ EEPROM_CACHE_PERFORM_OP,
+ EEPROM_NOT_IN_CACHE,
+ TWO_UINT32_TO_UINT64(i_opType,
+ i_eepromInfo.eepromRole),
+ TO_UINT64(i_eepromInfo.offset),
+ ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
+ ERRORLOG::ErrlUserDetailsTarget(i_target).addToLog(l_errl);
+ l_errl->collectTrace( EEPROM_COMP_NAME );
+ }
+
+ TRACSSCOMP( g_trac_eeprom, EXIT_MRK"eepromPerformOpCache() "
+ "Target HUID 0x%.08X Exit", TARGETING::get_huid(i_target));
+
+ }while(0);
+
+ return l_errl;
+}
+} \ No newline at end of file
diff --git a/src/usr/i2c/eepromdd.C b/src/usr/i2c/eepromdd.C
index ab7e804e1..2243e9b38 100755
--- a/src/usr/i2c/eepromdd.C
+++ b/src/usr/i2c/eepromdd.C
@@ -41,6 +41,11 @@
// va_list
#include "eepromCache.H"
#include "eepromdd_hardware.H"
+#include <i2c/eepromddreasoncodes.H>
+#ifdef __HOSTBOOT_RUNTIME
+// Need to be able to convert HB target id's to runtime target ids
+#include <targeting/attrrp.H>
+#endif
extern trace_desc_t* g_trac_eeprom;
@@ -87,6 +92,7 @@ errlHndl_t resolveSource(TARGETING::Target * i_target,
err = buildEepromRecordHeader(i_target,
io_i2cInfo,
l_eepromRecordHeader);
+#ifndef __HOSTBOOT_RUNTIME
// if lookupEepromAddr returns non-zero address
// then we know it exists in cache somewhere
if(lookupEepromCacheAddr(l_eepromRecordHeader))
@@ -99,7 +105,46 @@ errlHndl_t resolveSource(TARGETING::Target * i_target,
TRACDCOMP(g_trac_eeprom,"Eeprom not found in cache, looking at hardware");
o_source = EEPROM::HARDWARE;
}
-
+#else
+ uint8_t l_instance = TARGETING::AttrRP::getNodeId(i_target);
+ // if lookupEepromAddr returns non-zero address
+ // then we know it exists in cache somewhere
+ if(lookupEepromCacheAddr(l_eepromRecordHeader, l_instance))
+ {
+ TRACDCOMP(g_trac_eeprom,"Eeprom found in cache, looking at eecache");
+ o_source = EEPROM::CACHE;
+ }
+ else
+ {
+ /*@
+ * @errortype
+ * @moduleid EEPROM_RESOLVE_SOURCE
+ * @reasoncode EEPROM_CACHE_NOT_FOUND_IN_MAP
+ * @userdata1[0:7] i2c_master_huid
+ * @userdata1[8:9] port on i2c master eeprom slave is on
+ * @userdata1[10:11] engine on i2c master eeprom slave is on
+ * @userdata1[12:13] devAddr of eeprom slave
+ * @userdata1[14:15] muxSelect of eeprom slave (0xFF is not valid)
+ * @userdata2[0:7] size of eeprom
+ * @devdesc resolveSource failed to find cache in map during runtime
+ */
+ err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ EEPROM_RESOLVE_SOURCE,
+ EEPROM_CACHE_NOT_FOUND_IN_MAP,
+ TWO_UINT32_TO_UINT64(
+ l_eepromRecordHeader.completeRecord.i2c_master_huid,
+ TWO_UINT16_TO_UINT32(
+ TWO_UINT8_TO_UINT16(
+ l_eepromRecordHeader.completeRecord.port,
+ l_eepromRecordHeader.completeRecord.engine),
+ TWO_UINT8_TO_UINT16(
+ l_eepromRecordHeader.completeRecord.devAddr,
+ l_eepromRecordHeader.completeRecord.mux_select))),
+ l_eepromRecordHeader.completeRecord.cache_copy_size,
+ ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
+ }
+#endif
return err;
}
@@ -185,14 +230,16 @@ errlHndl_t eepromPerformOp( DeviceFW::OperationType i_opType,
{
break;
}
-
- // If the operation is a write we also need to
- // "write through" to HW after we write cache
+ // TODO RTC:212469 Complete Work needed for Axone i2c runtime support
+ #ifndef __HOSTBOOT_RUNTIME
if(i_opType == DeviceFW::WRITE)
{
+ // If the operation is a write we also need to
+ // "write through" to HW after we write cache
err = eepromPerformOpHW(i_opType, i_target,
io_buffer, io_buflen, i2cInfo);
}
+ #endif
}
else if(l_source == EEPROM::HARDWARE)
{
diff --git a/src/usr/i2c/i2c.mk b/src/usr/i2c/i2c.mk
index 6d4ef8935..0300d2c46 100644
--- a/src/usr/i2c/i2c.mk
+++ b/src/usr/i2c/i2c.mk
@@ -5,7 +5,7 @@
#
# OpenPOWER HostBoot Project
#
-# Contributors Listed Below - COPYRIGHT 2015
+# Contributors Listed Below - COPYRIGHT 2015,2019
# [+] International Business Machines Corp.
#
#
@@ -27,4 +27,4 @@ OBJS += eepromdd.o
OBJS += eepromdd_hardware.o
OBJS += eeprom_utils.o
OBJS += errlud_i2c.o
-OBJS += $(if $(CONFIG_SUPPORT_EEPROM_CACHING),eepromCache.o)
+OBJS += $(if $(CONFIG_SUPPORT_EEPROM_CACHING),eepromCache_common.o)
diff --git a/src/usr/i2c/makefile b/src/usr/i2c/makefile
index 535484752..10e55c9de 100644
--- a/src/usr/i2c/makefile
+++ b/src/usr/i2c/makefile
@@ -33,6 +33,7 @@ OBJS += i2c.o
OBJS += $(if $(CONFIG_TPMDD),tpmdd.o,)
OBJS += fapi_i2c_dd.o
OBJS += i2cTargetPres.o
+OBJS += $(if $(CONFIG_SUPPORT_EEPROM_CACHING),eepromCache.o)
SUBDIRS += test.d
SUBDIRS += runtime.d
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
OpenPOWER on IntegriCloud