summaryrefslogtreecommitdiffstats
path: root/src/usr/i2c
diff options
context:
space:
mode:
authorChristian Geddes <crgeddes@us.ibm.com>2019-06-21 16:11:32 -0500
committerDaniel M. Crowell <dcrowell@us.ibm.com>2019-06-26 16:45:21 -0500
commit3805319f1d630c6bc9c022b3e9eeb601aa3ffbf4 (patch)
tree0d5327e039f273391bfc9b20269968a683b6bd14 /src/usr/i2c
parent6fccf28881ecc8adb2c6f1ed877e1f41967ab8a6 (diff)
downloadtalos-hostboot-3805319f1d630c6bc9c022b3e9eeb601aa3ffbf4.tar.gz
talos-hostboot-3805319f1d630c6bc9c022b3e9eeb601aa3ffbf4.zip
Add HCDB Support for eeprom cache process
While parsing the EEPROMs of the system as part of the EECACHE process if we detect a part has been replaced, removed, or added then we must call markTargetChanged to notify hwas to take appropriate actions. This commit also introduces the new preloaded EECACHE section for simics. Change-Id: I9f2a8a62d5c6f9a6c66a0c0c7ed5ed86f7d94aec RTC: 211109 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/78762 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: William G. Hoffa <wghoffa@us.ibm.com> Reviewed-by: Roland Veloz <rveloz@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/usr/i2c')
-rw-r--r--src/usr/i2c/eepromCache.C232
-rw-r--r--src/usr/i2c/eepromCache.H15
2 files changed, 182 insertions, 65 deletions
diff --git a/src/usr/i2c/eepromCache.C b/src/usr/i2c/eepromCache.C
index 35aced423..6993f35ee 100644
--- a/src/usr/i2c/eepromCache.C
+++ b/src/usr/i2c/eepromCache.C
@@ -30,6 +30,7 @@
#include <devicefw/driverif.H>
#include <errl/errlmanager.H>
#include <fsi/fsiif.H>
+#include <hwas/hwasPlat.H>
#include "i2c.H"
#include "eepromCache.H"
#include <i2c/i2cif.H>
@@ -64,9 +65,10 @@ uint64_t g_eecachePnorSize = 0;
// Global map which is used as a way to quickly look up the virtual address
// of a given eeprom's cached data in EECACHE section
// Key = eepromRecordHeader with unique info filled out
-// Value = A struct of 2 virtual addresses , one points to header address
-// and other points to the location of the cache
-std::map<eepromRecordHeader, RecordAddresses_t> g_cachedEeproms;
+// Value = A struct of 2 uint64_t virtual addresses ,one points to header address
+// and other points to the location of the cache, and a byte indicating
+// 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
@@ -75,7 +77,7 @@ mutex_t g_eecacheMutex = MUTEX_INITIALIZER;
uint64_t lookupEepromCacheAddr(const eepromRecordHeader& i_eepromRecordHeader)
{
uint64_t l_vaddr = 0;
- std::map<eepromRecordHeader, RecordAddresses_t>::iterator l_it;
+ std::map<eepromRecordHeader, EeepromEntryMetaData_t>::iterator l_it;
// Wrap lookup in mutex because reads are not thread safe
mutex_lock(&g_eecacheMutex);
@@ -86,29 +88,13 @@ uint64_t lookupEepromCacheAddr(const eepromRecordHeader& i_eepromRecordHeader)
{
l_vaddr = l_it->second.cache_entry_address;
}
-
- if(l_vaddr == 0)
- {
- TRACFCOMP( g_trac_eeprom,
- "lookupEepromCacheAddr() 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;
}
uint64_t lookupEepromHeaderAddr(const eepromRecordHeader& i_eepromRecordHeader)
{
uint64_t l_vaddr = 0;
- std::map<eepromRecordHeader, RecordAddresses_t>::iterator l_it;
+ std::map<eepromRecordHeader, EeepromEntryMetaData_t>::iterator l_it;
// Wrap lookup in mutex because reads are not thread safe
mutex_lock(&g_eecacheMutex);
@@ -278,6 +264,58 @@ void printTableOfContents(void)
}
+/**
+*
+* @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)
{
@@ -347,7 +385,10 @@ errlHndl_t cacheEeprom(TARGETING::Target* i_target,
l_eepromInfo.eepromRole = i_eepromType;
// if the target is present, then this record is valid
- l_eepromRecordHeader.completeRecord.cached_copy_valid = i_present;
+ if(i_present)
+ {
+ l_eepromRecordHeader.completeRecord.cached_copy_valid = 1;
+ }
// buildEepromRecordHeader will call eepromReadAttributes to fill in l_eepromInfo
// with info looked up in attributes and also fill in l_eepromRecordHeader
@@ -502,7 +543,8 @@ errlHndl_t cacheEeprom(TARGETING::Target* i_target,
#ifdef CONFIG_CONSOLE
CONSOLE::displayf(EEPROM_COMP_NAME,
- "New EEPROM size detected for an existing part, clearing EEPROM cache and performing reconfig loop");
+ "New EEPROM size detected for an existing part,"
+ "clearing EEPROM cache and performing reconfig loop");
#endif
INITSERVICE::doShutdown(INITSERVICE::SHUTDOWN_DO_RECONFIG_LOOP);
@@ -514,7 +556,8 @@ errlHndl_t cacheEeprom(TARGETING::Target* i_target,
l_recordHeaderToUpdate->completeRecord.internal_offset;
TRACSSCOMP(g_trac_eeprom,
- "cacheEeprom() already found copy for eeprom role %d for target w/ HUID 0x.%08X",
+ "cacheEeprom() already found copy for eeprom role %d "
+ "for target w/ HUID 0x.%08X in EECACHE table of contents",
i_eepromType , TARGETING::get_huid(i_target));
break;
}
@@ -527,14 +570,24 @@ errlHndl_t cacheEeprom(TARGETING::Target* i_target,
reinterpret_cast<uint64_t>(l_recordHeaderToUpdate)))
{
TRACSSCOMP( g_trac_eeprom,
- "cacheEeprom() Eeprom w/ Role %d, HUID 0x.%08X added to cached list",
- i_eepromType , TARGETING::get_huid(i_target));
+ "cacheEeprom() Eeprom w/ Role %d, HUID 0x.%08X added to the global map of cached eeproms",
+ i_eepromType , TARGETING::get_huid(i_target));
}
else
{
+ // If this target's eeprom has already been cached in PNOR and our global map
+ // indicates the cache entry was updated this boot, then we must also
+ // mark this target associated with the cached eeprom as changed for hwas
+ if( hasEeepromChanged( l_eepromRecordHeader ) )
+ {
+ HWAS::markTargetChanged(i_target);
+ }
TRACSSCOMP( g_trac_eeprom,
- "cacheEeprom() Eeprom w/ Role %d, HUID 0x.%08X already in cached list",
+ "cacheEeprom() Eeprom w/ Role %d, HUID 0x.%08X already in global map of cached eeproms",
i_eepromType , TARGETING::get_huid(i_target));
+
+ // Cache entry has already been updated via another target, just break out
+ break;
}
// Only check if the cache is in sync with HARDWARE if there is an
@@ -574,11 +627,6 @@ errlHndl_t cacheEeprom(TARGETING::Target* i_target,
l_eepromVpd.eepromContentType);
}
- TRACSSCOMP(g_trac_eeprom,
- "cacheEeprom() Target 0x%.8X "
- "EEPROM_CONTENT_TYPE 0x%X",
- T::get_huid(i_target),
- l_eepromContentType);
bool l_isInSync = false;
@@ -610,10 +658,27 @@ errlHndl_t cacheEeprom(TARGETING::Target* i_target,
reinterpret_cast<uint8_t *>(l_eecacheSectionHeaderPtr) +
l_eepromRecordHeader.completeRecord.internal_offset;
- memset( l_internalSectionAddr, 0xFF ,
+ memset( l_internalSectionAddr, 0xFF ,
(l_recordHeaderToUpdate->completeRecord.cache_copy_size * KILOBYTE));
- l_updateContents = false;
+ l_updateContents = false;
+
+ setIsValidCacheEntry(l_eepromRecordHeader, false);
+
+ TRACFCOMP( g_trac_eeprom, "Detected Master 0x%.08X"
+ " Engine 0x%.02X Port 0x%.02X"
+ " MuxSelect 0x%.02X DevAddr 0x%.02X"
+ " no longer present, clearing cache and marking cache as invalid",
+ l_recordHeaderToUpdate->completeRecord.i2c_master_huid,
+ l_recordHeaderToUpdate->completeRecord.engine,
+ l_recordHeaderToUpdate->completeRecord.port,
+ l_recordHeaderToUpdate->completeRecord.mux_select,
+ l_recordHeaderToUpdate->completeRecord.devAddr);
+
+ setEeepromChanged(l_eepromRecordHeader);
+ // We have cleared the cache entry, this indicates we have found a part has been removed.
+ // Mark that the target is changed in hwas.
+ HWAS::markTargetChanged(i_target);
}
// If target is present there is nothing in the
@@ -630,15 +695,34 @@ errlHndl_t cacheEeprom(TARGETING::Target* i_target,
l_updateContents = false;
l_updateHeader = false;
}
+ // The check below makes sure that is isnt a new entry, because
+ // new entries do not have internal_offset set in header.
+ // If there is a matching header entry in PNOR marked 'invalid'
+ // but we now see the target as present, this indicates a replacement
+ // part has been added where a part was removed
+ else if(l_recordHeaderToUpdate->completeRecord.internal_offset != UNSET_INTERNAL_OFFSET_VALUE)
+ {
+ TRACFCOMP(g_trac_eeprom, "cacheEeprom() Detected replacement of a part"
+ " Master 0x%.08X Engine 0x%.02X"
+ " Port 0x%.02X MuxSelect 0x%.02X DevAddr 0x%.02X"
+ " that was previously removed, we will update the cache with new part's eeproms contents",
+ l_recordHeaderToUpdate->completeRecord.i2c_master_huid,
+ l_recordHeaderToUpdate->completeRecord.engine,
+ l_recordHeaderToUpdate->completeRecord.port,
+ l_recordHeaderToUpdate->completeRecord.mux_select,
+ l_recordHeaderToUpdate->completeRecord.devAddr);
+ }
// Above we have determined whether the contents of the eeprom at
// hand need to have their contents updated. Only do the following
// steps that update the eeprom's cached data if we were told to do so.
- if(l_updateContents )
+ if( l_updateContents )
{
assert(l_recordHeaderToUpdateIndex != INVALID_EEPROM_INDEX,
"More than MAX_EEPROMS_VERSION_1 in system XML");
+ TRACFCOMP( g_trac_eeprom, "cacheEeprom() updating cache entry");
+
void * l_tmpBuffer;
l_tmpBuffer = malloc(l_eepromLen);
@@ -704,13 +788,18 @@ errlHndl_t cacheEeprom(TARGETING::Target* i_target,
break;
}
- // If cache copy was not valid before, it is now valid, we must update the header
- if (!l_recordHeaderToUpdate->completeRecord.cached_copy_valid)
- {
- l_eepromRecordHeader.completeRecord.cached_copy_valid = 0x01;
- l_updateHeader = true;
- }
-
+ // Set mark_target_changed and cached_copy_valid and update set updateHeader
+ // Since we have copied stuff in the cache is valid, and been updated.
+ // Even if this is a replacement ( cached_copy_valid was already 1) we
+ // must set mark_target_changed so just always update the header
+ setEeepromChanged(l_eepromRecordHeader);
+ // We will update header in PNOR below so no need to call
+ // setIsValidCacheEntry right here
+ l_eepromRecordHeader.completeRecord.cached_copy_valid = 1;
+ l_updateHeader = true;
+ // We have updated the cache entry, this indicates we have found a "new" part.
+ // Mark that the target is changed in hwas.
+ HWAS::markTargetChanged(i_target);
}
// Above we have determined whether the header entry for the eeprom at
@@ -718,6 +807,7 @@ errlHndl_t cacheEeprom(TARGETING::Target* i_target,
// the eeprom's header entry if we were told to do so.
if(l_updateHeader)
{
+ TRACFCOMP( g_trac_eeprom, "cacheEeprom() updating header entry");
TRACDBIN( g_trac_eeprom, "cacheEeprom: l_eecacheSectionHeaderPtr currently ",
l_eecacheSectionHeaderPtr,
sizeof(eecacheSectionHeader));
@@ -832,31 +922,43 @@ errlHndl_t setIsValidCacheEntry(const TARGETING::Target * i_target,
{
errlHndl_t l_errl = nullptr;
eepromRecordHeader l_eepromRecordHeader;
- eepromRecordHeader * l_eepromRecordHeaderToUpdate;
- std::map<eepromRecordHeader, RecordAddresses_t>::iterator l_headerMapIterator;
-
eeprom_addr_t l_eepromInfo;
- l_eepromInfo.eepromRole = i_eepromRole;
do{
- TRACFCOMP( g_trac_eeprom, ENTER_MRK"setIsValidCacheEntry() "
+ TRACDCOMP( g_trac_eeprom, ENTER_MRK"setIsValidCacheEntry() "
"Target HUID 0x%.08X Eeprom Role = %d Enter",
TARGETING::get_huid(i_target), l_eepromInfo.eepromRole);
- // Take the input paramters and use them to build a eeprom record header we can search with
- l_errl = buildEepromRecordHeader(const_cast<TARGETING::Target *>(i_target),
- l_eepromInfo,
- l_eepromRecordHeader);
+ l_eepromInfo.eepromRole = i_eepromRole;
+ l_errl = buildEepromRecordHeader(const_cast<TARGETING::Target *>(i_target), l_eepromInfo, l_eepromRecordHeader);
if(l_errl)
{
break;
}
+ l_errl = setIsValidCacheEntry(l_eepromRecordHeader, i_isValid);
+
+ }while(0);
+
+ return l_errl;
+}
+
+errlHndl_t setIsValidCacheEntry(const eepromRecordHeader& i_eepromRecordHeader, bool i_isValid)
+{
+ errlHndl_t l_errl = nullptr;
+ eepromRecordHeader * l_eepromRecordHeaderToUpdate;
+ std::map<eepromRecordHeader, EeepromEntryMetaData_t>::iterator l_headerMapIterator;
+
+ do{
+
+ TRACDCOMP( g_trac_eeprom, ENTER_MRK"setIsValidCacheEntry() ");
+
+
// Find the address of the header entry in the table of contents of the EECACHE pnor section
l_eepromRecordHeaderToUpdate =
- reinterpret_cast<eepromRecordHeader *>(lookupEepromHeaderAddr(l_eepromRecordHeader));
+ reinterpret_cast<eepromRecordHeader *>(lookupEepromHeaderAddr(i_eepromRecordHeader));
if(l_eepromRecordHeaderToUpdate == 0)
{
@@ -880,22 +982,22 @@ errlHndl_t setIsValidCacheEntry(const TARGETING::Target * i_target,
EEPROM_INVALIDATE_CACHE,
EEPROM_CACHE_NOT_FOUND_IN_MAP,
TWO_UINT32_TO_UINT64(
- l_eepromRecordHeader.completeRecord.i2c_master_huid,
+ i_eepromRecordHeader.completeRecord.i2c_master_huid,
TWO_UINT16_TO_UINT32(
TWO_UINT8_TO_UINT16(
- l_eepromRecordHeader.completeRecord.port,
- l_eepromRecordHeader.completeRecord.engine),
+ i_eepromRecordHeader.completeRecord.port,
+ i_eepromRecordHeader.completeRecord.engine),
TWO_UINT8_TO_UINT16(
- l_eepromRecordHeader.completeRecord.devAddr,
- l_eepromRecordHeader.completeRecord.mux_select))),
- l_eepromRecordHeader.completeRecord.cache_copy_size,
+ i_eepromRecordHeader.completeRecord.devAddr,
+ i_eepromRecordHeader.completeRecord.mux_select))),
+ i_eepromRecordHeader.completeRecord.cache_copy_size,
ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
break;
}
// Ensure that information at the address we just looked up matches the record we built up
if( memcmp(&l_eepromRecordHeaderToUpdate->uniqueRecord.uniqueID,
- &l_eepromRecordHeader.uniqueRecord.uniqueID,
+ &i_eepromRecordHeader.uniqueRecord.uniqueID,
NUM_BYTE_UNIQUE_ID ) != 0 )
{
TRACFCOMP(g_trac_eeprom,ERR_MRK"setIsValidCacheEntry: Attempting to invalidate cache for an"
@@ -917,15 +1019,15 @@ errlHndl_t setIsValidCacheEntry(const TARGETING::Target * i_target,
EEPROM_INVALIDATE_CACHE,
EEPROM_CACHE_NOT_FOUND_IN_PNOR,
TWO_UINT32_TO_UINT64(
- l_eepromRecordHeader.completeRecord.i2c_master_huid,
+ i_eepromRecordHeader.completeRecord.i2c_master_huid,
TWO_UINT16_TO_UINT32(
TWO_UINT8_TO_UINT16(
- l_eepromRecordHeader.completeRecord.port,
- l_eepromRecordHeader.completeRecord.engine),
+ i_eepromRecordHeader.completeRecord.port,
+ i_eepromRecordHeader.completeRecord.engine),
TWO_UINT8_TO_UINT16(
- l_eepromRecordHeader.completeRecord.devAddr,
- l_eepromRecordHeader.completeRecord.mux_select))),
- l_eepromRecordHeader.completeRecord.cache_copy_size,
+ i_eepromRecordHeader.completeRecord.devAddr,
+ i_eepromRecordHeader.completeRecord.mux_select))),
+ i_eepromRecordHeader.completeRecord.cache_copy_size,
ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
break;
}
diff --git a/src/usr/i2c/eepromCache.H b/src/usr/i2c/eepromCache.H
index fa0c340bd..9e0e140d8 100644
--- a/src/usr/i2c/eepromCache.H
+++ b/src/usr/i2c/eepromCache.H
@@ -151,6 +151,21 @@ errlHndl_t setIsValidCacheEntry(const TARGETING::Target * i_target,
/**
*
+* @brief Update the record entry in the Table of Contents of the EECACHE
+* section of pnor to either mark the contents of the cache to be
+* valid or invalid
+*
+* @param[in] i_eepromRecordHeader eepromRecord oject already filled in (including eepromRole)
+*
+* @param[in] i_isValid Mark eeprom cache valid or invalid ?
+*
+* @return errlHndl_t - nullptr if successful, otherwise a pointer to the
+* error log.
+*
+*/
+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
*
OpenPOWER on IntegriCloud