diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/include/usr/i2c/eepromddreasoncodes.H | 6 | ||||
-rw-r--r-- | src/include/usr/vmmconst.h | 4 | ||||
-rw-r--r-- | src/usr/i2c/eepromCache.C | 588 | ||||
-rw-r--r-- | src/usr/i2c/eepromCache.H | 106 | ||||
-rw-r--r-- | src/usr/i2c/eepromCache_common.C | 326 | ||||
-rwxr-xr-x | src/usr/i2c/eepromdd.C | 55 | ||||
-rw-r--r-- | src/usr/i2c/i2c.mk | 4 | ||||
-rw-r--r-- | src/usr/i2c/makefile | 1 | ||||
-rw-r--r-- | src/usr/i2c/runtime/makefile | 6 | ||||
-rw-r--r-- | src/usr/i2c/runtime/rt_eepromCache.C | 285 | ||||
-rw-r--r-- | src/usr/vpd/makefile | 1 | ||||
-rw-r--r-- | src/usr/vpd/rtvpd_load.C | 18 | ||||
-rw-r--r-- | src/usr/vpd/spd.C | 2 | ||||
-rw-r--r-- | src/usr/vpd/vpd.mk | 1 | ||||
-rw-r--r-- | src/usr/vpd/vpd_common.C | 4 |
15 files changed, 941 insertions, 466 deletions
diff --git a/src/include/usr/i2c/eepromddreasoncodes.H b/src/include/usr/i2c/eepromddreasoncodes.H index c08935ab4..41de06dfa 100644 --- a/src/include/usr/i2c/eepromddreasoncodes.H +++ b/src/include/usr/i2c/eepromddreasoncodes.H @@ -58,6 +58,8 @@ enum eepromModuleId EEPROM_CLEAR_EECACHE = 0x08, EEPROM_CACHE_PERFORM_OP = 0x09, EEPROM_INVALIDATE_CACHE = 0x0A, + EEPROM_RESOLVE_SOURCE = 0x0B, + EEPROM_CACHE_INIT_RT = 0x0C, }; /** @@ -92,6 +94,10 @@ enum eepromReasonCode // what eeproms have been cached was not found EEPROM_CACHE_NOT_FOUND_IN_PNOR = EEPROM_COMP_ID | 0x10, // An entry we thought would be in the the EECACHE section of PNOR seems // to be missing + EEPROM_CACHE_NO_VPD_IN_RSV_MEM = EEPROM_COMP_ID | 0x11, // When looking up the VPD section in reserved memory no entry was found. + EEPROM_DUPLICATE_CACHE_ENTRY = EEPROM_COMP_ID | 0x12 // While parsing eecache found in reserved memory we found at least two + // cache entries that had identical "unique" identifiers + // (see structs defined in eeprom_const.H) }; enum UserDetailsTypes diff --git a/src/include/usr/vmmconst.h b/src/include/usr/vmmconst.h index b6841eea4..bd6a889c1 100644 --- a/src/include/usr/vmmconst.h +++ b/src/include/usr/vmmconst.h @@ -208,9 +208,13 @@ enum BlockPriority #define VMM_MODULE_VPD_SIZE (512*KILOBYTE) /* must be 64KB aligned */ #define VMM_CENTAUR_VPD_SIZE (256*KILOBYTE) /* must be 64KB aligned */ #define VMM_DIMM_JEDEC_VPD_SIZE (256*KILOBYTE) /* must be 64KB aligned */ +#ifndef CONFIG_SUPPORT_EEPROM_CACHING #define VMM_RT_VPD_SIZE ( VMM_MODULE_VPD_SIZE + \ VMM_CENTAUR_VPD_SIZE + \ VMM_DIMM_JEDEC_VPD_SIZE ) +#else +#define VMM_RT_VPD_SIZE (512*KILOBYTE) /* 64KB aligned (size EECACHE section size - ecc) */ +#endif /** Internode communication area outside of the HB image. 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 diff --git a/src/usr/vpd/makefile b/src/usr/vpd/makefile index 728750fca..9ef60d788 100644 --- a/src/usr/vpd/makefile +++ b/src/usr/vpd/makefile @@ -31,7 +31,6 @@ include vpd.mk #include unique objects OBJS += vpd.o OBJS += dimmPres.o -OBJS += ocmb_spd.o OBJS += rtvpd_load.o SUBDIRS += test.d diff --git a/src/usr/vpd/rtvpd_load.C b/src/usr/vpd/rtvpd_load.C index 26ad6f031..f12d23d01 100644 --- a/src/usr/vpd/rtvpd_load.C +++ b/src/usr/vpd/rtvpd_load.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2013,2017 */ +/* Contributors Listed Below - COPYRIGHT 2013,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -108,6 +108,7 @@ errlHndl_t VPD::vpd_load_rt_image(uint64_t & i_vpd_addr) do { +#ifndef CONFIG_SUPPORT_EEPROM_CACHING void* vptr = reinterpret_cast<void*>(i_vpd_addr); uint8_t* vpd_ptr = reinterpret_cast<uint8_t*>(vptr); @@ -136,6 +137,21 @@ errlHndl_t VPD::vpd_load_rt_image(uint64_t & i_vpd_addr) { break; } +#else + // In Axone we store all contents of EEPROMs in EECACHE + // so copy the EECACHE pnor section to the space in reserved + // memory allocated for VPD. + void* vptr = reinterpret_cast<void*>(i_vpd_addr); + uint8_t* vpd_ptr = reinterpret_cast<uint8_t*>(vptr); + + err = bld_vpd_image(PNOR::EECACHE, + vpd_ptr, + VMM_RT_VPD_SIZE); + if(err) + { + break; + } +#endif } while( 0 ); diff --git a/src/usr/vpd/spd.C b/src/usr/vpd/spd.C index afa7417a6..dbae8feae 100644 --- a/src/usr/vpd/spd.C +++ b/src/usr/vpd/spd.C @@ -1314,13 +1314,11 @@ errlHndl_t fetchDataFromEepromType(uint64_t i_byteAddr, } else if (i_eepromType == TARGETING::EEPROM_CONTENT_TYPE_DDIMM) { -#ifndef __HOSTBOOT_RUNTIME errl = ocmbFetchData(i_target, i_byteAddr, i_numBytes, o_data, EEPROM::AUTOSELECT); -#endif } return errl; diff --git a/src/usr/vpd/vpd.mk b/src/usr/vpd/vpd.mk index d5717e653..aa3333291 100644 --- a/src/usr/vpd/vpd.mk +++ b/src/usr/vpd/vpd.mk @@ -34,4 +34,5 @@ OBJS += cvpd.o OBJS += pvpd.o OBJS += dvpd.o OBJS += spd.o +OBJS += ocmb_spd.o OBJS += errlud_vpd.o diff --git a/src/usr/vpd/vpd_common.C b/src/usr/vpd/vpd_common.C index 0196b8be8..92c4e9294 100644 --- a/src/usr/vpd/vpd_common.C +++ b/src/usr/vpd/vpd_common.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2013,2018 */ +/* Contributors Listed Below - COPYRIGHT 2013,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -156,6 +156,8 @@ bool resolveVpdSource( TARGETING::Target * i_target, } } + TRACDCOMP(g_trac_vpd,"resolveVpdSource: o_vpdSource = %s" ,o_vpdSource == VPD::PNOR ? "PNOR" : "SEEPROM" ); + return badConfig; } |