diff options
Diffstat (limited to 'src/usr/i2c/eepromCache.C')
-rw-r--r-- | src/usr/i2c/eepromCache.C | 668 |
1 files changed, 467 insertions, 201 deletions
diff --git a/src/usr/i2c/eepromCache.C b/src/usr/i2c/eepromCache.C index 72541df33..dc8bb15db 100644 --- a/src/usr/i2c/eepromCache.C +++ b/src/usr/i2c/eepromCache.C @@ -24,176 +24,239 @@ /* IBM_PROLOG_END_TAG */ #include <builtins.h> +#include <stdarg.h> +#include <sys/mm.h> +#include <limits.h> #include <devicefw/driverif.H> -#include "eepromdd.H" #include <errl/errlmanager.H> #include <fsi/fsiif.H> #include "i2c.H" +#include "eepromCache.H" #include <i2c/i2cif.H> #include <i2c/eepromif.H> -#include <i2c/i2creasoncodes.H> -#include <i2c/eepromCache_const.H> +#include <i2c/eepromddreasoncodes.H> #include <initservice/initserviceif.H> #include <initservice/initsvcreasoncodes.H> -#include <sys/mm.h> -#include <limits.h> #include <pnor/pnorif.H> -#include <stdarg.h> #include <vpd/vpd_if.H> +#include <errl/errludtarget.H> -extern trace_desc_t* g_trac_i2c; +extern trace_desc_t* g_trac_eeprom; -// #define TRACSSCOMP(args...) TRACFCOMP(args) +//#define TRACSSCOMP(args...) TRACFCOMP(args) #define TRACSSCOMP(args...) -namespace I2C +namespace EEPROM { -uint64_t g_eecachePnorVaddr; -uint64_t g_eecachePnorSize; - +// 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 +// pnor code everytime. +uint64_t g_eecachePnorVaddr = 0; +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 = virtual address pointing to the cached eeprom data in pnor +std::map<eepromRecordHeader, uint64_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; -/** - * @brief Write all 0xFFs to the EECACHE section in pnor to clear out the - * eeprom cache information. - * @return errlHndl_t - */ -errlHndl_t clearEEcache() +uint64_t lookupEepromAddr(const eepromRecordHeader& i_eepromRecordHeader) { - errlHndl_t l_errl = nullptr; - - memset(reinterpret_cast<void *>(g_eecachePnorVaddr), 0xFF, g_eecachePnorSize); - - // Flush the page to make sure it gets to the PNOR - int rc = mm_remove_pages( FLUSH, reinterpret_cast<void *>(g_eecachePnorVaddr), g_eecachePnorSize ); + uint64_t l_vaddr = 0; + std::map<eepromRecordHeader, uint64_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( rc ) + if(l_it != g_cachedEeproms.end()) { - TRACFCOMP(g_trac_i2c,ERR_MRK"cacheEeprom: Error from mm_remove_pages trying for flush contents write to pnor! rc=%d",rc); - /*@ - * @errortype - * @moduleid I2C_CLEAR_EECACHE - * @reasoncode I2C_FAILED_TO_FLUSH_CONTENTS - * @userdata1 Requested Address - * @userdata2 rc from mm_remove_pages - * @devdesc clearEEcache mm_remove_pages FLUSH failed - */ - l_errl = new ERRORLOG::ErrlEntry( - ERRORLOG::ERRL_SEV_UNRECOVERABLE, - I2C_CLEAR_EECACHE, - I2C_FAILED_TO_FLUSH_CONTENTS, - (uint64_t)g_eecachePnorVaddr, - TO_UINT64(rc), - ERRORLOG::ErrlEntry::ADD_SW_CALLOUT); - - l_errl->collectTrace(I2C_COMP_NAME); + l_vaddr = l_it->second; } - return l_errl; + return l_vaddr; } -/** - * @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 - * in the cache yet, add it to the cache. - * - * @param[in] i_target Presence detect target - * @param[in] i_present Describes whether or not target is present - * ( CANNOT RELY ON HWAS_STATE!! ) - * @param[in] i_eepromType Describes which EEPROM associated to the target - * that is being requested to cache. (PRIMARY/BACKUP etc) - * @return errlHndl_t - */ -errlHndl_t cacheEeprom(TARGETING::Target* i_target, - bool i_present, - EEPROM::eeprom_chip_types_t i_eepromType) +errlHndl_t buildEepromRecordHeader(TARGETING::Target * i_target, + eeprom_addr_t & io_eepromInfo, + eepromRecordHeader & o_eepromRecordHeader) { - TRACSSCOMP( g_trac_i2c, "cacheEeprom() ENTER Target HUID 0x%.08X ", TARGETING::get_huid(i_target)); - errlHndl_t l_errl = nullptr; + TARGETING::Target * l_muxTarget = nullptr; TARGETING::Target * l_i2cMasterTarget = nullptr; TARGETING::TargetService& l_targetService = TARGETING::targetService(); - - EEPROM::eeprom_addr_t l_eepromInfo; - eecacheSectionHeader * l_eecacheSectionHeaderPtr; - - // Initially assume we will want to update both the entry in the header - // as well as the contents in the body of the EECACHE section - bool l_updateHeader = true; - bool l_updateContents = true; + errlHndl_t l_errl = nullptr; do{ - // eepromReadAttributes keys off the eepromRole value - // to determine what attribute to lookup to get eeprom info - l_eepromInfo.eepromRole = i_eepromType; - l_errl = eepromReadAttributes(i_target, l_eepromInfo); + l_errl = eepromReadAttributes(i_target, io_eepromInfo); if(l_errl) { - TRACFCOMP( g_trac_i2c, - "cacheEeprom() error occured reading eeprom attributes for eepromType %d, target 0x%.08X, returning!!", - i_eepromType, + 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(I2C_COMP_NAME); + 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( l_eepromInfo.i2cMuxPath); + l_muxTarget = l_targetService.toTarget( io_eepromInfo.i2cMuxPath); if(l_muxTarget == nullptr) { - TRACFCOMP( g_trac_i2c, - "cacheEeprom() Mux target associated with target 0x%.08X resolved to a nullptr , check attribute for eepromType %d. Skipping Cache", + 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), - i_eepromType); + io_eepromInfo.eepromRole); /*@ * @errortype - * @moduleid I2C_CACHE_EEPROM - * @reasoncode I2C_MUX_TARGET_NOT_FOUND + * @moduleid EEPROM_CACHE_EEPROM + * @reasoncode EEPROM_I2C_MUX_PATH_ERROR * @userdata1 HUID of target we want to cache - * @userdata2[0:31] Type of EEPROM we are caching - * @userdata2[32:63] Boolean is target present or not - * @devdesc cacheEeprom invalid mux target + * @userdata2 Type of EEPROM we are caching + * @devdesc buildEepromRecordHeader invalid mux target */ l_errl = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, - I2C_CACHE_EEPROM, - I2C_MUX_TARGET_NOT_FOUND, + EEPROM_CACHE_EEPROM, + EEPROM_I2C_MUX_PATH_ERROR, TARGETING::get_huid(i_target), - TWO_UINT32_TO_UINT64(i_eepromType, i_present), + io_eepromInfo.eepromRole, ERRORLOG::ErrlEntry::ADD_SW_CALLOUT); - l_errl->collectTrace(I2C_COMP_NAME); + 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( l_eepromInfo.i2cMasterPath ); + l_i2cMasterTarget = l_targetService.toTarget( io_eepromInfo.i2cMasterPath ); if(l_i2cMasterTarget == nullptr) { - TRACFCOMP( g_trac_i2c, - "cacheEeprom() I2C Master target associated with target 0x%.08X resolved to a nullptr , check attribute for eepromType %d. Skipping Cache ", + 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), - i_eepromType); + io_eepromInfo.eepromRole); /*@ * @errortype - * @moduleid I2C_CACHE_EEPROM - * @reasoncode INVALID_MASTER_TARGET + * @moduleid EEPROM_CACHE_EEPROM + * @reasoncode EEPROM_I2C_MASTER_PATH_ERROR * @userdata1 HUID of target we want to cache - * @userdata2[0:31] Type of EEPROM we are caching - * @userdata2[32:63] Boolean is target present or not - * @devdesc cacheEeprom invalid master target + * @userdata2 Type of EEPROM we are caching + * @devdesc buildEepromRecordHeader invalid master target */ l_errl = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, - I2C_CACHE_EEPROM, - INVALID_MASTER_TARGET, + EEPROM_CACHE_EEPROM, + EEPROM_I2C_MASTER_PATH_ERROR, TARGETING::get_huid(i_target), - TWO_UINT32_TO_UINT64(i_eepromType, i_present), + io_eepromInfo.eepromRole, ERRORLOG::ErrlEntry::ADD_SW_CALLOUT); - l_errl->collectTrace(I2C_COMP_NAME); + 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 + +bool addEepromToCachedList(const eepromRecordHeader & i_eepromRecordHeader) +{ + bool l_matchFound = true; + std::map<eepromRecordHeader, uint64_t>::iterator it; + + // 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] = g_eecachePnorVaddr + i_eepromRecordHeader.completeRecord.internal_offset; + 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 + * in the cache yet, add it to the cache. + * + * @param[in] i_target Presence detect target + * @param[in] i_present Describes whether or not target is present + * ( CANNOT RELY ON HWAS_STATE!! ) + * @param[in] i_eepromType Describes which EEPROM associated to the target + * that is being requested to cache. (PRIMARY/BACKUP etc) + * @return errlHndl_t + */ +errlHndl_t cacheEeprom(TARGETING::Target* i_target, + bool i_present, + EEPROM::EEPROM_ROLE i_eepromType) +{ + TRACSSCOMP( g_trac_eeprom, "cacheEeprom() ENTER Target HUID 0x%.08X ", TARGETING::get_huid(i_target)); + errlHndl_t l_errl = nullptr; + + EEPROM::eeprom_addr_t l_eepromInfo; + eecacheSectionHeader * l_eecacheSectionHeaderPtr; + eepromRecordHeader l_eepromRecordHeader; + + // Initially assume we will want to update both the entry in the header + // as well as the contents in the body of the EECACHE section + bool l_updateHeader = true; + bool l_updateContents = true; + + do{ + // eepromReadAttributes keys off the eepromRole value + // to determine what attribute to lookup to get eeprom info + l_eepromInfo.eepromRole = i_eepromType; + + // if the target is present, then this record is valid + l_eepromRecordHeader.completeRecord.cached_copy_valid = i_present; + + // buildEepromRecordHeader will call eepromReadAttributes to fill in l_eepromInfo + // with info looked up in attributes and also fill in l_eepromRecordHeader + l_errl = buildEepromRecordHeader(i_target, l_eepromInfo, l_eepromRecordHeader); + + TRACDBIN( g_trac_eeprom, "cacheEeprom: l_eepromRecordHeader currently ", + &l_eepromRecordHeader, + sizeof(eepromRecordHeader)); + + if(l_errl) + { + // buildEepromRecordHeader should have traced any relavent information if + // is was needed, just break out and pass the error along break; } @@ -207,14 +270,14 @@ errlHndl_t cacheEeprom(TARGETING::Target* i_target, if(l_errl) { - TRACFCOMP( g_trac_i2c, "cacheEeprom() Failed while looking up the EECACHE section in PNOR!!"); + TRACFCOMP( g_trac_eeprom, "cacheEeprom() Failed while looking up the EECACHE section in PNOR!!"); break; } mutex_lock(&g_eecacheMutex); g_eecachePnorVaddr = l_sectionInfo.vaddr; g_eecachePnorSize = l_sectionInfo.size; - TRACFCOMP( g_trac_i2c, "cacheEeprom() vaddr for EECACHE start = 0x%lx , size = 0x%lx!!", + TRACFCOMP( g_trac_eeprom, "cacheEeprom() vaddr for EECACHE start = 0x%lx , size = 0x%lx!!", g_eecachePnorVaddr, g_eecachePnorSize); mutex_unlock(&g_eecacheMutex); } @@ -232,7 +295,7 @@ errlHndl_t cacheEeprom(TARGETING::Target* i_target, // if nothing has been cached before then version should // be set to be the latest version of the struct available l_eecacheSectionHeaderPtr->version = EECACHE_VERSION_LATEST; - TRACFCOMP( g_trac_i2c, + TRACFCOMP( g_trac_eeprom, "cacheEeprom() Found Empty Cache, set version of cache structure to be 0x%.02x", EECACHE_VERSION_1); } @@ -244,30 +307,17 @@ errlHndl_t cacheEeprom(TARGETING::Target* i_target, // This means the start of first eeprom's cached data will be immediately // following the end of the EECACHE header. l_eecacheSectionHeaderPtr->end_of_cache = sizeof(eecacheSectionHeader); - TRACFCOMP( g_trac_i2c, + TRACFCOMP( g_trac_eeprom, "cacheEeprom() Found Empty Cache, set end of cache to be 0x%.04x (End of ToC)", sizeof(eecacheSectionHeader)); } - // 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 - eepromRecordHeader l_eepromRecord = {l_i2cMasterTarget->getAttr<TARGETING::ATTR_HUID>(), - (uint8_t)l_eepromInfo.port, - (uint8_t)l_eepromInfo.engine, - (uint8_t)l_eepromInfo.devAddr, - l_muxTarget->getAttr<TARGETING::ATTR_HUID>(), - l_eepromInfo.i2cMuxBusSelector, - (uint8_t)l_eepromInfo.devSize_KB, - 0, // Default internal offset to be 0 - i_present}; - size_t l_eepromLen = l_eepromInfo.devSize_KB * KILOBYTE; // Parse through PNOR section header to determine if a copy of this // eeprom already exists, or if we need to add it, and where we should add it // if we need to. - eepromRecordHeader * l_recordHeaderToUpdate; + eepromRecordHeader * l_recordHeaderToUpdate = nullptr; // Initialize this to an INVALID value. This way we catch the case where // cache has 50 records and we cannot add anymore. In that case l_recordHeaderToUpdateIndex @@ -279,77 +329,132 @@ errlHndl_t cacheEeprom(TARGETING::Target* i_target, // Keep track of current record so we can use outside for loop l_recordHeaderToUpdate = &l_eecacheSectionHeaderPtr->recordHeaders[i]; - // If internal_offset is non-zero then we will assume this address has been filled - if(l_recordHeaderToUpdate->internal_offset != UNSET_INTERNAL_OFFSET_VALUE) + + // If internal_offset is UNSET_INTERNAL_OFFSET_VALUE then we will assume this address not been filled + if(l_recordHeaderToUpdate->completeRecord.internal_offset == UNSET_INTERNAL_OFFSET_VALUE) + { + assert((l_eecacheSectionHeaderPtr->end_of_cache + l_eepromLen) < g_eecachePnorSize, + "Sum of system EEPROMs is larger than space allocated for EECACHE pnor section"); + + l_recordHeaderToUpdateIndex = i; + // Set this new eepromRecord's offset within the EECACHE PNOR section + // to be the current "end of cache" offset in the toc. + l_eepromRecordHeader.completeRecord.internal_offset = l_eecacheSectionHeaderPtr->end_of_cache; + l_eecacheSectionHeaderPtr->end_of_cache += l_eepromLen; + l_updateContents = i_present; + break; + } + + // Compare the eeprom record we are checking against the eeprom records we are iterating through + // but ignore the last 9 bytes which have chip size, the offset into this pnor section where the + // record exists, and a byte that tells us if its valid or not + if( memcmp(l_recordHeaderToUpdate, &l_eepromRecordHeader, NUM_BYTE_UNIQUE_ID ) == 0 ) { - // Compare the eeprom record we are checking against the eeprom records we are iterating through - // but ignore the last 9 bytes which have chip size, the offset into this pnor section where the - // record exists, and a byte that tells us if its valid or not - if( memcmp(l_recordHeaderToUpdate, &l_eepromRecord, RECORD_COMPARE_SIZE ) == 0 ) + l_recordHeaderToUpdateIndex = i; + + if( l_recordHeaderToUpdate->completeRecord.cache_copy_size != l_eepromRecordHeader.completeRecord.cache_copy_size) { - l_recordHeaderToUpdateIndex = i; - if( l_recordHeaderToUpdate->record_size != l_eepromRecord.record_size) + // This indicates that a part size has changed , caching + // algorithm cannot account for size changes. + // Invalidate entire cache and TI to trigger re-ipl + l_errl = PNOR::clearSection(PNOR::EECACHE); + + // If there was an error clearing the cache commit is because we are TIing + if(l_errl) { - // This indicates that a part size has changed , caching - // algorithm cannot account for size changes. - // Invalidate entire cache and TI to trigger re-ipl - l_errl = clearEEcache(); - - // If there was an error clearing the cache commit is because we are TIing - if(l_errl) - { - errlCommit(l_errl, I2C_COMP_ID); - } - - INITSERVICE::doShutdown(INITSERVICE::SHUTDOWN_DO_RECONFIG_LOOP); + errlCommit(l_errl, EEPROM_COMP_ID); } - if(l_recordHeaderToUpdate->record_valid) + /*@ + * @errortype ERRORLOG::ERRL_SEV_PREDICTIVE + * @moduleid EEPROM_CACHE_EEPROM + * @reasoncode EEPROM_NEW_DEVICE_DETECTED + * @userdata1[0:31] Old Size of Eeprom + * @userdata1[32:63] New Size of Eeprom + * @userdata2[0:31] HUID of I2C Master + * @userdata2[32:39] Port + * @userdata2[40:47] Engine + * @userdata2[48:55] HUID of I2C Master + * @userdata2[56:63] HUID of I2C Master + * @devdesc New part has likely been loaded into the system. + * @custdesc Firmware detected new part and is restarting + */ + l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_PREDICTIVE, + EEPROM_CACHE_EEPROM, + EEPROM_NEW_DEVICE_DETECTED, + TWO_UINT32_TO_UINT64(l_recordHeaderToUpdate->completeRecord.cache_copy_size , + l_eepromRecordHeader.completeRecord.cache_copy_size), + 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)))); + errlCommit(l_errl, EEPROM_COMP_ID); + + #ifdef CONFIG_CONSOLE + CONSOLE::displayf(EEPROM_COMP_NAME, + "New EEPROM size detected for an existing part, clearing EEPROM cache and performing reconfig loop"); + #endif + + INITSERVICE::doShutdown(INITSERVICE::SHUTDOWN_DO_RECONFIG_LOOP); + } + + // + // At this point we have found a match in the PNOR but we need + // to decide what all needs an update + // + + // Stash the internal_offset of the section we found in so we can add + // this record to g_cachedEeproms for later use + l_eepromRecordHeader.completeRecord.internal_offset = + l_recordHeaderToUpdate->completeRecord.internal_offset; + + + if(l_recordHeaderToUpdate->completeRecord.cached_copy_valid) + { + // If the existing eeprom record is valid, then only update the + // contents if the SN/PN for current HW do not match the eeprom + // record. (target must be present to cache) + + // TODO RTC:203788 add lookup for PN and SN matches + //if( !i_present || PNandSNMatch ) { - // If the existing eeprom record is valid, then only update the - // contents if the SN/PN for current HW do not match the eeprom - // record. (target must be present to cache) - - // TODO RTC:203788 add lookup for PN and SN matches - //if( !i_present || PNandSNMatch ) - { - l_updateContents = false; - } - - // If target is present there is nothing in the - // header to update - if( i_present ) - { - l_updateHeader = false; - } + l_updateContents = false; } - else if(!i_present) + + // If target is present there is nothing in the + // header to update + if( i_present ) { - // If the target is not present, then do not update contents or header - l_updateContents = false; l_updateHeader = false; } - - TRACSSCOMP( g_trac_i2c, "cacheEeprom() already found copy for eeprom role %d for target w/ HUID 0x.%08X", - i_eepromType , TARGETING::get_huid(i_target)); - break; } - } - else - { - assert((l_eecacheSectionHeaderPtr->end_of_cache + l_eepromLen) < g_eecachePnorSize, - "Sum of system EEPROMs is larger than space allocated for EECACHE pnor section"); + else if(!i_present) + { + // If the target is not present, then do not update contents or header + l_updateContents = false; + l_updateHeader = false; + } - l_recordHeaderToUpdateIndex = i; - // Set this new eepromRecord's offset within the EECACHE PNOR section - // to be the current "end of cache" offset in the toc. - l_eepromRecord.internal_offset = l_eecacheSectionHeaderPtr->end_of_cache; - l_eecacheSectionHeaderPtr->end_of_cache += l_eepromLen; - l_updateContents = i_present; + TRACSSCOMP( g_trac_eeprom, "cacheEeprom() already found copy for eeprom role %d for target w/ HUID 0x.%08X", + i_eepromType , TARGETING::get_huid(i_target)); break; } } + if(!addEepromToCachedList(l_eepromRecordHeader)) + { + TRACSSCOMP( g_trac_eeprom, "cacheEeprom() Eeprom w/ Role %d, HUID 0x.%08X added to cached list", + i_eepromType , TARGETING::get_huid(i_target)); + } + else + { + TRACSSCOMP( g_trac_eeprom, "cacheEeprom() Eeprom w/ Role %d, HUID 0x.%08X already in cached list", + i_eepromType , TARGETING::get_huid(i_target)); + } + // Above we have determined whether the contents of the eeprom at // hand need to have their contents updated. Only do the following @@ -364,22 +469,22 @@ errlHndl_t cacheEeprom(TARGETING::Target* i_target, l_tmpBuffer = malloc(l_eepromLen); void * l_internalSectionAddr = - reinterpret_cast<uint8_t *>(l_eecacheSectionHeaderPtr) + l_eepromRecord.internal_offset; + reinterpret_cast<uint8_t *>(l_eecacheSectionHeaderPtr) + l_eepromRecordHeader.completeRecord.internal_offset; - TRACSSCOMP( g_trac_i2c, "cacheEeprom() passing the following into deviceOp eeprom address : huid 0x%.08X length 0x%.08X" , - get_huid(i_target), l_eepromLen); + TRACSSCOMP( g_trac_eeprom, "cacheEeprom() passing the following into deviceOp eeprom address : huid 0x%.08X length 0x%.08X vaddr %p" , + get_huid(i_target), l_eepromLen, l_internalSectionAddr); // Copy vpd contents to cache l_errl = deviceOp(DeviceFW::READ, i_target, l_tmpBuffer, l_eepromLen, - DEVICE_EEPROM_ADDRESS(i_eepromType, 0)); + DEVICE_EEPROM_ADDRESS(i_eepromType, 0, VPD::SEEPROM)); // If an error occurred during the eeprom read then free the tmp buffer and break out if( l_errl) { - TRACFCOMP(g_trac_i2c,ERR_MRK"cacheEeprom: Error occured reading from EEPROM type %d for HUID 0x%.08X!", + TRACFCOMP(g_trac_eeprom,ERR_MRK"cacheEeprom: Error occured reading from EEPROM type %d for HUID 0x%.08X!", i_eepromType,get_huid(i_target)); free(l_tmpBuffer); break; @@ -392,26 +497,26 @@ errlHndl_t cacheEeprom(TARGETING::Target* i_target, int rc = mm_remove_pages( FLUSH, l_internalSectionAddr, l_eepromLen ); if( rc ) { - TRACFCOMP(g_trac_i2c,ERR_MRK"cacheEeprom: Error from mm_remove_pages trying for flush contents write to pnor! rc=%d",rc); + TRACFCOMP(g_trac_eeprom,ERR_MRK"cacheEeprom: Error from mm_remove_pages trying for flush contents write to pnor! rc=%d",rc); /*@ * @errortype - * @moduleid I2C_CACHE_EEPROM - * @reasoncode I2C_FAILED_TO_FLUSH_CONTENTS + * @moduleid EEPROM_CACHE_EEPROM + * @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, - I2C_CACHE_EEPROM, - I2C_FAILED_TO_FLUSH_CONTENTS, + EEPROM_CACHE_EEPROM, + EEPROM_FAILED_TO_FLUSH_CONTENTS, (uint64_t)l_internalSectionAddr, TO_UINT64(rc), ERRORLOG::ErrlEntry::ADD_SW_CALLOUT); } else { - TRACSSCOMP( g_trac_i2c, "cacheEeprom() %.08X bytes of eeprom data related to %.08X have been written to %p" , + TRACSSCOMP( g_trac_eeprom, "cacheEeprom() %.08X bytes of eeprom data related to %.08X have been written to %p" , l_eepromLen, get_huid(i_target), l_internalSectionAddr); } @@ -430,27 +535,30 @@ errlHndl_t cacheEeprom(TARGETING::Target* i_target, // the eeprom's header entry if we were told to do so. if(l_updateHeader) { + TRACDBIN( g_trac_eeprom, "cacheEeprom: l_eecacheSectionHeaderPtr currently ", + l_eecacheSectionHeaderPtr, + sizeof(eecacheSectionHeader)); // Copy the local eepromRecord header struct with the info about the // new eeprom we want to add to the cache to the open slot we found - memcpy(l_recordHeaderToUpdate , &l_eepromRecord, sizeof(eepromRecordHeader)); + memcpy(l_recordHeaderToUpdate , &l_eepromRecordHeader, sizeof(eepromRecordHeader)); // Flush the page to make sure it gets to the PNOR int rc = mm_remove_pages( FLUSH, l_recordHeaderToUpdate, sizeof(eepromRecordHeader) ); if( rc ) { - TRACFCOMP(g_trac_i2c,ERR_MRK"cacheEeprom: Error from mm_remove_pages trying for flush header write to pnor, rc=%d",rc); + TRACFCOMP(g_trac_eeprom,ERR_MRK"cacheEeprom: Error from mm_remove_pages trying for flush header write to pnor, rc=%d",rc); /*@ * @errortype - * @moduleid I2C_CACHE_EEPROM - * @reasoncode I2C_FAILED_TO_FLUSH_HEADER + * @moduleid EEPROM_CACHE_EEPROM + * @reasoncode EEPROM_FAILED_TO_FLUSH_HEADER * @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, - I2C_CACHE_EEPROM, - I2C_FAILED_TO_FLUSH_HEADER, + EEPROM_CACHE_EEPROM, + EEPROM_FAILED_TO_FLUSH_HEADER, (uint64_t)l_recordHeaderToUpdate, TO_UINT64(rc), ERRORLOG::ErrlEntry::ADD_SW_CALLOUT); @@ -458,12 +566,10 @@ errlHndl_t cacheEeprom(TARGETING::Target* i_target, } } - TRACDBIN( g_trac_i2c, "cacheEeprom: l_eecacheSectionHeaderPtr currently ", - l_eecacheSectionHeaderPtr, - sizeof(eecacheSectionHeader)); + }while(0); - TRACSSCOMP( g_trac_i2c, "cacheEeprom() EXIT Target HUID 0x%.08X ", TARGETING::get_huid(i_target)); + TRACSSCOMP( g_trac_eeprom, "cacheEeprom() EXIT Target HUID 0x%.08X ", TARGETING::get_huid(i_target)); return l_errl; } @@ -498,9 +604,9 @@ errlHndl_t genericI2CEepromCache(DeviceFW::OperationType i_opType, bool l_present = (bool)va_arg(i_args,uint64_t); // second param is the type of EEPROM type we wish to cache (PRIMARY vs BACKUP etc) - EEPROM::eeprom_chip_types_t l_eepromType = (EEPROM::eeprom_chip_types_t)va_arg(i_args,uint64_t); + EEPROM::EEPROM_ROLE l_eepromType = (EEPROM::EEPROM_ROLE)va_arg(i_args,uint64_t); - TRACSSCOMP( g_trac_i2c, ENTER_MRK"genericI2CEepromCache() " + TRACSSCOMP( g_trac_eeprom, ENTER_MRK"genericI2CEepromCache() " "Target HUID 0x%.08X Enter", TARGETING::get_huid(i_target)); do{ @@ -508,7 +614,7 @@ errlHndl_t genericI2CEepromCache(DeviceFW::OperationType i_opType, l_errl = cacheEeprom(i_target, l_present, l_eepromType); if(l_errl) { - TRACFCOMP(g_trac_i2c, + TRACFCOMP(g_trac_eeprom, ERR_MRK"cacheEeprom: An error occured while attempting to cache eeprom for 0x%.08X", TARGETING::get_huid(i_target)); break; @@ -516,7 +622,7 @@ errlHndl_t genericI2CEepromCache(DeviceFW::OperationType i_opType, }while(0); - TRACSSCOMP( g_trac_i2c, EXIT_MRK"genericI2CEepromCache() " + TRACSSCOMP( g_trac_eeprom, EXIT_MRK"genericI2CEepromCache() " "Target HUID 0x%.08X EXIT", TARGETING::get_huid(i_target)); return l_errl; @@ -537,4 +643,164 @@ DEVICE_REGISTER_ROUTE( DeviceFW::READ, TARGETING::TYPE_DIMM, genericI2CEepromCache ); +#endif + +errlHndl_t eepromPerformOpCache(DeviceFW::OperationType i_opType, + TARGETING::Target * i_target, + void * io_buffer, + size_t i_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; + } + + uint64_t l_eepromCacheVaddr = lookupEepromAddr(l_eepromRecordHeader); + + // Ensure that a copy of the eeprom exists in our map of cached eeproms + if(l_eepromCacheVaddr) + { + 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, i_buflen, l_eepromCacheVaddr); + + // Make sure that offset + buflen are less than the total size of the eeprom + if(i_eepromInfo.offset + i_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(i_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), i_buflen); + } + else if(i_opType == DeviceFW::WRITE) + { + memcpy(reinterpret_cast<void *>(l_eepromCacheVaddr + i_eepromInfo.offset), io_buffer, i_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), + i_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 ); + } + + 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 |