void Daemon::collectTracePages() { // Clear indication from clients. iv_service->iv_daemon->clearSignal(); // Collect buffer pages from front-end. BufferPage* srcPages[BUFFER_COUNT]; for (size_t i = 0; i < BUFFER_COUNT; i++) { iv_curPages[i] = srcPages[i] = iv_service->iv_buffers[i]->claimPages(); iv_curOffset[i] = 0; } char* contBuffer = NULL; size_t contBufferSize = 0; // Process buffer pages. do { size_t whichBuffer = BUFFER_COUNT; Entry* whichEntry = NULL; uint64_t minTimeStamp = UINT64_MAX; // Find the entry with the earliest timestamp. for (size_t i = 0; i < BUFFER_COUNT; i++) { if (NULL == iv_curPages[i]) continue; Entry* entry = reinterpret_cast<Entry*>( &((&(iv_curPages[i]->data[0]))[iv_curOffset[i]]) ); trace_bin_entry_t* binEntry = reinterpret_cast<trace_bin_entry_t*>( &(entry->data[0]) ); // Wait for entry to be committed. while(unlikely(entry->committed == 0)) { task_yield(); } isync(); uint64_t curTimeStamp = TWO_UINT32_TO_UINT64(binEntry->stamp.tbh, binEntry->stamp.tbl); if (curTimeStamp < minTimeStamp) { whichBuffer = i; whichEntry = entry; minTimeStamp = curTimeStamp; } } // Did not find another entry, our work is done. if (whichBuffer == BUFFER_COUNT) { break; } // Increment pointers to next buffer entry. iv_curOffset[whichBuffer] += whichEntry->size + sizeof(Entry); if (iv_curOffset[whichBuffer] >= iv_curPages[whichBuffer]->usedSize) { iv_curPages[whichBuffer] = iv_curPages[whichBuffer]->next; iv_curOffset[whichBuffer] = 0; } trace_bin_entry_t* contEntry = reinterpret_cast<trace_bin_entry_t*>(&whichEntry->data[0]); // Calculate the sizes of the entry. size_t contEntryDataLength = contEntry->head.length + sizeof(trace_bin_entry_t); size_t contEntrySize = whichEntry->comp->iv_compNameLen + contEntryDataLength; // Allocate a new continuous trace page if needed. if ((NULL == contBuffer) || ((contBufferSize + contEntrySize) >= PAGESIZE)) { if (NULL != contBuffer) { sendContBuffer(contBuffer, contBufferSize); // contBuffer pointer is transfered to mailbox now. } contBuffer = reinterpret_cast<char*>(malloc(PAGESIZE)); memset(contBuffer, '\0', PAGESIZE); contBuffer[0] = TRACE_BUF_CONT; contBufferSize = 1; } // Add entry to continous trace. memcpy(&contBuffer[contBufferSize], whichEntry->comp->iv_compName, whichEntry->comp->iv_compNameLen); contBufferSize += whichEntry->comp->iv_compNameLen; memcpy(&contBuffer[contBufferSize], &whichEntry->data[0], contEntryDataLength); contBufferSize += contEntryDataLength; // Allocate a new back-end entry. Entry* mainBuffEntry = NULL; while (NULL == (mainBuffEntry = iv_last->claimEntry(whichEntry->size + sizeof(Entry)))) { BufferPage* n = BufferPage::allocate(true); n->next = iv_last; iv_last->prev = n; iv_last = n; } // Move entry from front-end buffer to back-end. replaceEntry(whichEntry, mainBuffEntry); } while(1); // Send remainder of continous trace buffer. if (NULL != contBuffer) { if (contBufferSize > 1) { sendContBuffer(contBuffer, contBufferSize); // contBuffer pointer is transfered to mailbox now. } else { free(contBuffer); } } // Release pages. for (size_t i = 0; i < BUFFER_COUNT; i++) { // Toggle lock to ensure no trace extract currently going on. iv_service->iv_buffers[i]->consumerOp(); while(srcPages[i]) { BufferPage* tmp = srcPages[i]->next; BufferPage::deallocate(srcPages[i]); srcPages[i] = tmp; } } }
/** * @brief Performs a presence detect operation on a Membuf Chip. * * This function does FSI presence detect, following the pre-defined prototype * for a device-driver framework function. * * @param[in] i_opType Operation type, see DeviceFW::OperationType * in driverif.H * @param[in] i_target Presence detect target * @param[in/out] io_buffer Read: Pointer to output data storage * Write: Pointer to input data storage * @param[in/out] io_buflen Input: size of io_buffer (in bytes, always 1) * Output: Success = 1, Failure = 0 * @param[in] i_accessType DeviceFW::AccessType enum (userif.H) * @param[in] i_args This is an argument list for DD framework. * In this function, there are no arguments. * @return errlHndl_t */ errlHndl_t membPresenceDetect(DeviceFW::OperationType i_opType, TARGETING::Target* i_target, void* io_buffer, size_t& io_buflen, int64_t i_accessType, va_list i_args) { errlHndl_t l_errl = NULL; uint32_t l_saved_plid = 0; if (unlikely(io_buflen < sizeof(bool))) { TRACFCOMP(g_trac_fsi, ERR_MRK "FSI::membPresenceDetect> Invalid data length: %d", io_buflen); /*@ * @errortype * @moduleid FSI::MOD_FSIPRES_MEMBPRESENCEDETECT * @reasoncode FSI::RC_INVALID_LENGTH * @userdata1 Data Length * @devdesc presenceDetect> Invalid data length (!= 1 bytes) */ l_errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, FSI::MOD_FSIPRES_MEMBPRESENCEDETECT, FSI::RC_INVALID_LENGTH, TO_UINT64(io_buflen), true /*SW error*/); io_buflen = 0; return l_errl; } // First look for FSI presence bits bool fsi_present = isSlavePresent(i_target); // Next look for memb FRU VPD bool cvpd_present = false; bool check_for_cvpd = true; #ifdef CONFIG_CVPD_READ_FROM_HW check_for_cvpd = fsi_present; #endif if ( check_for_cvpd ) { cvpd_present = VPD::cvpdPresent( i_target ); } #if defined(CONFIG_CVPD_READ_FROM_HW) && defined(CONFIG_CVPD_READ_FROM_PNOR) if( cvpd_present ) { // Check if the VPD data in the PNOR matches the SEEPROM l_errl = VPD::ensureCacheIsInSync( i_target ); if( l_errl ) { // Save this plid to use later l_saved_plid = l_errl->plid(); cvpd_present = false; TRACFCOMP(g_trac_fsi,ERR_MRK "FSI::membPresenceDetect> Error during ensureCacheIsInSync (CVPD)" ); errlCommit( l_errl, FSI_COMP_ID ); } } else { // FSI is not present, invalidate MVPD in the PNOR l_errl = VPD::invalidatePnorCache(i_target); if (l_errl) { TRACFCOMP( g_trac_fsi, "Error invalidating MVPD in PNOR" ); errlCommit( l_errl, FSI_COMP_ID ); } } #endif // Finally compare the 2 methods if( fsi_present != cvpd_present ) { TRACFCOMP(g_trac_fsi, ERR_MRK "FSI::membPresenceDetect> " "FSI (=%d) and VPD (=%d) do not agree for %.8X", fsi_present, cvpd_present, TARGETING::get_huid(i_target)); /*@ * @errortype * @moduleid FSI::MOD_FSIPRES_MEMBPRESENCEDETECT * @reasoncode FSI::RC_FSI_CVPD_MISMATCH * @userdata1 HUID of membuffer * @userdata2[0:31] FSI Presence * @userdata2[32:63] VPD Presence * @devdesc presenceDetect> FSI and CVPD do not agree */ l_errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, FSI::MOD_FSIPRES_MEMBPRESENCEDETECT, FSI::RC_FSI_CVPD_MISMATCH, TARGETING::get_huid(i_target), TWO_UINT32_TO_UINT64( fsi_present, cvpd_present)); // Callout the membuf l_errl->addHwCallout( i_target, HWAS::SRCI_PRIORITY_LOW, HWAS::NO_DECONFIG, HWAS::GARD_NULL ); // If there is a saved PLID, apply it to this error log if (l_saved_plid) { l_errl->plid(l_saved_plid); } // Add FFDC for the target to an error log getFsiFFDC( FFDC_PRESENCE_FAIL, l_errl, i_target); // Add FSI and VPD trace l_errl->collectTrace("FSI"); l_errl->collectTrace("VPD"); // commit this log and move on errlCommit( l_errl, FSI_COMP_ID ); } bool present = fsi_present && cvpd_present; if( present ) { //Fsp sets PN/SN so if there is none, do it here if(!INITSERVICE::spBaseServicesEnabled()) { // set part and serial number attributes for current target VPD::setPartAndSerialNumberAttributes( i_target ); } } memcpy(io_buffer, &present, sizeof(present)); io_buflen = sizeof(present); return NULL; }
//************************************************************************** // FREQVOLTSVC::setWofFrequencyUpliftSelected //************************************************************************** void setWofFrequencyUpliftSelected() { // get mrw data TARGETING::Target* l_pTopLevel = NULL; (void)TARGETING::targetService().getTopLevelTarget(l_pTopLevel); ATTR_WOF_FREQUENCY_UPLIFT_type l_upliftTable = {{{0}}}; ATTR_WOF_PROC_SORT_type l_procSortTable = {{0}}; ATTR_NOMINAL_FREQ_MHZ_type l_sysNomFreqMhz = l_pTopLevel->getAttr<ATTR_NOMINAL_FREQ_MHZ>(); ATTR_WOF_ENABLED_type l_wofEnabled = l_pTopLevel->getAttr < TARGETING::ATTR_WOF_ENABLED > (); // tryGetAttr used due to complex data type. Expected to always work. if (!l_pTopLevel->tryGetAttr<ATTR_WOF_FREQUENCY_UPLIFT>(l_upliftTable)) { // The zero initialized values will be used for the select array TRACFCOMP(g_fapiTd, "Failed to get ATTR_WOF_FREQUENCY_UPLIFT"); } // tryGetAttr used due to complex data type. Expected to always work. if ( !l_pTopLevel->tryGetAttr<ATTR_WOF_PROC_SORT>(l_procSortTable)) { // Not finding the sort table will result in not finding the index // which will result in a log later TRACFCOMP(g_fapiTd, "Failed to get ATTR_WOF_PROC_SORT"); } // get the list of procs TargetHandleList l_procTargetList; getAllChips(l_procTargetList, TYPE_PROC, true); // for each proc, fill in Wof Frequency Uplift Selected attribute for (TargetHandleList::const_iterator l_proc_iter = l_procTargetList.begin(); l_proc_iter != l_procTargetList.end(); ++l_proc_iter) { TARGETING::Target * l_pProcTarget = *l_proc_iter; // find number of active cores TARGETING::TargetHandleList l_presCoreList; getChildAffinityTargetsByState( l_presCoreList, const_cast<TARGETING::Target*>(l_pProcTarget), TARGETING::CLASS_UNIT, TARGETING::TYPE_CORE, TARGETING::UTIL_FILTER_PRESENT); uint8_t l_activeCores = l_presCoreList.size(); TRACDCOMP(g_fapiTd, "setWofFrequencyUpliftSelected:" " number of active cores is %d ", l_activeCores); // find WOF index. For example: // ATTR_WOF_PROC_SORT = // Cores/Nom Freq/Index // 8 3325 1 // 10 2926 2 // 12 2561 3 // 12 3093 4 // Use WOF index=3 for active cores=12 && nom freq=2561 uint8_t l_wofIndex = 0; for (uint8_t i=0;i<4;i++) { if ( (l_activeCores == l_procSortTable[i][0]) && (l_sysNomFreqMhz == l_procSortTable[i][1]) ) { l_wofIndex = l_procSortTable[i][2]; break; } } TRACDCOMP(g_fapiTd, "setWofFrequencyUpliftSelected:" " WOF index is %d ", l_wofIndex); // validate WOF index ATTR_WOF_FREQUENCY_UPLIFT_SELECTED_type l_selectedTable = {{0}}; if ( (!l_wofIndex) || (l_wofIndex > 4)) { if (l_wofEnabled) // log error if WOF enabled { TRACFCOMP(g_fapiTd, "setWofFrequencyUpliftSelected:" " No WOF table index match found HUID:0x%08X" " active cores=%d, nom freq=%d, index=%d", l_pProcTarget->getAttr<TARGETING::ATTR_HUID>(), l_activeCores, l_sysNomFreqMhz, l_wofIndex); errlHndl_t l_err = NULL; /*@ * @errortype * @moduleid fapi::MOD_GET_WOF_FREQ_UPLIFT_SELECTED * @reasoncode fapi::RC_INVALID_WOF_INDEX * @userdata1[0:31] Proc HUID * @userdata1[32:63] WOF Freq Uplift Index * @userdata2[0:31] Number of active cores * @userdata2[32:63] Nomimal Frequency * @devdesc When WOF is enabled, the WOF Freq * Uplift index should be 1,2,3, or 4 */ l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, fapi::MOD_GET_WOF_FREQ_UPLIFT_SELECTED, fapi::RC_INVALID_WOF_INDEX, TWO_UINT32_TO_UINT64( l_pProcTarget->getAttr<TARGETING::ATTR_HUID>(), l_wofIndex), TWO_UINT32_TO_UINT64( l_activeCores, l_sysNomFreqMhz)); // Callout HW as WOF mrw data is incorrect l_err->addHwCallout(l_pProcTarget, HWAS::SRCI_PRIORITY_MED, HWAS::NO_DECONFIG, HWAS::GARD_NULL); // Include WOF processor sort table TRACFBIN (g_fapiTd, "WOF processor sort table", l_procSortTable, sizeof(l_procSortTable)); l_err->collectTrace(FAPI_TRACE_NAME); // log error and keep going errlCommit(l_err,HWPF_COMP_ID); } // make sure zeros are set in the selected table attribute memset(l_selectedTable, 0, sizeof(l_selectedTable)); } else { // use index to set Wof Frequency Uplift selected attribute // note: mrw index is 1 based memcpy(l_selectedTable, &l_upliftTable[l_wofIndex-1][0][0], sizeof(l_selectedTable)); } if (!l_pProcTarget->trySetAttr<ATTR_WOF_FREQUENCY_UPLIFT_SELECTED> (l_selectedTable)) { //unlikely, crash TRACFCOMP(g_fapiTd, "Failed to set ATTR_WOF_FREQUENCY_UPLIFT_SELECTED"); assert(0); } } return; }
static errlHndl_t load_pnor_section(PNOR::SectionId i_section, uint64_t i_physAddr) { TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,ENTER_MRK"load_pnor_section()"); errlHndl_t err = nullptr; #ifdef CONFIG_SECUREBOOT // Securely load section TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,"load_pnor_section: secure section load of secId=0x%X (%s)", i_section, PNOR::SectionIdToString(i_section)); err = PNOR::loadSecureSection(i_section); if (err) { return err; } // Do not need to unload since we have plenty of memory at this point. #endif // Get the section info from PNOR. PNOR::SectionInfo_t pnorSectionInfo; err = PNOR::getSectionInfo( i_section, pnorSectionInfo ); if( err != nullptr ) { TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "load_pnor_section: Could not get section info from %x", i_section); return err; } // XZ repository: http:git.tukaani.org/xz.git // Header specifics can be found in xz/doc/xz-file-format.txt const uint8_t HEADER_MAGIC[]= { 0xFD, '7', 'z', 'X', 'Z', 0x00 }; uint8_t* l_pnor_header = reinterpret_cast<uint8_t *>(pnorSectionInfo.vaddr); bool l_pnor_is_XZ_compressed = (0 == memcmp(l_pnor_header, HEADER_MAGIC, sizeof(HEADER_MAGIC))); TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "load_pnor_section: is XZ_compressed: %d", l_pnor_is_XZ_compressed); // This assumes that the maximum decompression ratio will always be less // than 1:16 (compressed:uncompressed). This works because XZ compression // is usually 14.1%, the decompressor does not need the exact size, and // we have all of mainstore memory at this point. uint32_t uncompressedPayloadSize = l_pnor_is_XZ_compressed ? (pnorSectionInfo.size * 16) : pnorSectionInfo.size; const uint32_t originalPayloadSize = pnorSectionInfo.size; printk( "Loading PNOR section %d (%s) %d bytes @0x%lx\n", i_section, pnorSectionInfo.name, originalPayloadSize, i_physAddr ); void * loadAddr = NULL; // Map in the physical memory we are loading into. // If we are not xz compressed, the uncompressedSize // is equal to the original size. loadAddr = mm_block_map( reinterpret_cast<void*>( i_physAddr ), uncompressedPayloadSize ); // Print out inital progress bar. #ifdef CONFIG_CONSOLE const int progressSteps = 80; int progress = 0; for ( int i = 0; i < progressSteps; ++i ) { printk( "." ); } printk( "\r" ); #endif if(!l_pnor_is_XZ_compressed) { // Load the data block by block and update the progress bar. const uint32_t BLOCK_SIZE = 4096; for ( uint32_t i = 0; i < originalPayloadSize; i += BLOCK_SIZE ) { memcpy( reinterpret_cast<void*>( reinterpret_cast<uint64_t>(loadAddr) + i ), reinterpret_cast<void*>( pnorSectionInfo.vaddr + i ), std::min( originalPayloadSize - i, BLOCK_SIZE ) ); #ifdef CONFIG_CONSOLE for ( int new_progress = (i * progressSteps) / originalPayloadSize; progress <= new_progress; progress++ ) { printk( "=" ); } #endif } #ifdef CONFIG_CONSOLE printk( "\n" ); #endif } if(l_pnor_is_XZ_compressed) { struct xz_buf b; struct xz_dec *s; enum xz_ret ret; xz_crc32_init(); s = xz_dec_init(XZ_SINGLE, 0); if(s == NULL) { TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,ERR_MRK "load_pnor_section: XZ Embedded Initialization failed"); return err; } static const uint64_t compressed_SIZE = originalPayloadSize; static const uint64_t decompressed_SIZE = uncompressedPayloadSize; b.in = reinterpret_cast<uint8_t *>( pnorSectionInfo.vaddr); b.in_pos = 0; b.in_size = compressed_SIZE; b.out = reinterpret_cast<uint8_t *>(loadAddr); b.out_pos = 0; b.out_size = decompressed_SIZE; ret = xz_dec_run(s, &b); if(ret == XZ_STREAM_END) { TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, "load_pnor_section: The %s section was decompressed.", pnorSectionInfo.name); }else { TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,ERR_MRK "load_pnor_section: xz-embedded returned an error, ", "the ret is %d",ret); /*@ * @errortype * @reasoncode fapi::RC_INVALID_RETURN_XZ_CODE * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE * @moduleid fapi::MOD_START_XZ_PAYLOAD * @devdesc xz-embedded has returned an error. * the return code can be found in xz.h * @custdesc Error uncompressing payload image from * boot flash * @userdata1 Return code from xz-embedded * @userdata2[0:31] Original Payload Size * @userdata2[32:63] Uncompressed Payload Size */ err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, fapi::MOD_START_XZ_PAYLOAD, fapi::RC_INVALID_RETURN_XZ_CODE, ret,TWO_UINT32_TO_UINT64( originalPayloadSize, uncompressedPayloadSize)); err->addProcedureCallout(HWAS::EPUB_PRC_PHYP_CODE, HWAS::SRCI_PRIORITY_HIGH); } //Clean up memory xz_dec_end(s); } int rc = 0; rc = mm_block_unmap(reinterpret_cast<void *>(loadAddr)); if(rc) { TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,ERR_MRK "load_pnor_section: mm_block_unmap returned 1"); /*@ * @errortype * @reasoncode fapi::RC_MM_UNMAP_ERR * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE * @moduleid fapi::MOD_START_XZ_PAYLOAD * @devdesc mm_block_unmap returned incorrectly with 0 * @custdesc Error unmapping memory section */ err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, fapi::MOD_START_XZ_PAYLOAD, fapi::RC_MM_UNMAP_ERR, 0,0,0); } return err; }
errlHndl_t RtPnor::writeToDevice( uint64_t i_procId, PNOR::SectionId i_section, uint64_t i_offset, size_t i_size, bool i_ecc, void* i_src ) { TRACFCOMP(g_trac_pnor, ENTER_MRK"RtPnor::writeToDevice: i_offset=0x%X, " "i_procId=%d sec=%d size=0x%X ecc=%d", i_offset, i_procId, i_section, i_size, i_ecc); errlHndl_t l_err = nullptr; uint8_t* l_eccBuffer = nullptr; do { void* l_dataToWrite = i_src; size_t l_writeSize = i_size; size_t l_writeSizePlusECC = (i_size * 9)/8; uint64_t l_offset = i_offset; // apply ECC to data if needed if( i_ecc ) { l_eccBuffer = new uint8_t[l_writeSizePlusECC]; PNOR::ECC::injectECC( reinterpret_cast<uint8_t*>(i_src), l_writeSize, reinterpret_cast<uint8_t*>(l_eccBuffer) ); l_dataToWrite = reinterpret_cast<void*>(l_eccBuffer); l_writeSize = l_writeSizePlusECC; l_offset = (i_offset * 9)/8; } const char* l_partitionName = SectionIdToString(i_section); if (g_hostInterfaces && g_hostInterfaces->pnor_write) { //make call into opal to write the data int l_rc = g_hostInterfaces->pnor_write(i_procId, l_partitionName,l_offset,l_dataToWrite,l_writeSize); if (l_rc != static_cast<int>(l_writeSize)) { TRACFCOMP(g_trac_pnor, "RtPnor::writeToDevice: pnor_write failed " "proc:%d, part:%s, offset:0x%X, size:0x%X, dataPt:0x%X," " rc:%d", i_procId, l_partitionName, l_offset, l_writeSize, l_dataToWrite, l_rc); /*@ * @errortype * @moduleid PNOR::MOD_RTPNOR_WRITETODEVICE * @reasoncode PNOR::RC_PNOR_WRITE_FAILED * @userdata1[00:31] rc returned from pnor_write * @userdata1[32:63] section ID * @userdata2[00:31] offset within the section * @userdata2[32:63] size of data written in bytes * @devdesc g_hostInterfaces->pnor_write failed * @custdesc Error accessing system firmware flash */ l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, PNOR::MOD_RTPNOR_WRITETODEVICE, PNOR::RC_PNOR_WRITE_FAILED, TWO_UINT32_TO_UINT64(l_rc, i_section), TWO_UINT32_TO_UINT64(l_offset, l_writeSize), true); break; } else if( l_rc != static_cast<int>(l_writeSize) ) { TRACFCOMP( g_trac_pnor, "RtPnor::writeToDevice: only read 0x%X bytes, expecting 0x%X", l_rc, l_writeSize ); } } else { TRACFCOMP(g_trac_pnor,"RtPnor::writeToDevice: This version of" " OPAL does not support pnor_write"); /*@ * @errortype * @moduleid PNOR::MOD_RTPNOR_WRITETODEVICE * @reasoncode PNOR::RC_PNOR_WRITE_NOT_SUPPORTED * @devdesc g_hostInterfaces->pnor_write not supported * @custdesc Error accessing system firmware flash */ //@todo Add PNOR callout RTC:116145 l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, PNOR::MOD_RTPNOR_WRITETODEVICE, PNOR::RC_PNOR_WRITE_NOT_SUPPORTED, 0,0,true); break; } } while(0); if( l_eccBuffer ) { delete[] l_eccBuffer; } TRACFCOMP(g_trac_pnor, EXIT_MRK"RtPnor::writeToDevice" ); return l_err; }
//************************************************************************** // FREQVOLTSVC::getSysFreq //************************************************************************** errlHndl_t getSysFreq( uint32_t & o_sysVPDPowerSaveMinFreqMhz, TARGETING::ATTR_NOMINAL_FREQ_MHZ_type & o_sysNomFreqMhz, TARGETING::ATTR_FREQ_CORE_MAX_type & o_sysVPDTurboMaxFreqMhz, TARGETING::ATTR_ULTRA_TURBO_FREQ_MHZ_type & o_sysVPDUltraTurboMinFreqMhz) { uint32_t l_minsysVPDTurboMaxFreqMhz = 0; uint32_t l_maxsysVPDPowerSaveMinFreqMhz = 0; uint32_t l_minsysVPDUltraTurboFreqMhz = 0; fapi::ReturnCode l_rc; errlHndl_t l_err = NULL; do { o_sysNomFreqMhz = 0; o_sysVPDTurboMaxFreqMhz = 0; o_sysVPDPowerSaveMinFreqMhz = 0; o_sysVPDUltraTurboMinFreqMhz = 0; //Get the top level (system) target handle TARGETING::Target* l_pTopLevel = NULL; (void)TARGETING::targetService().getTopLevelTarget(l_pTopLevel); // Assert on failure getting system target assert( l_pTopLevel != NULL ); // Retrun Fvmin as ultra turbo freq if WOF enabled. ATTR_WOF_ENABLED_type l_wofEnabled = l_pTopLevel->getAttr < TARGETING::ATTR_WOF_ENABLED > (); TRACFCOMP(g_fapiTd,"getSysFreq: WOF_ENABLED is %d ",l_wofEnabled); //Filter functional unit TARGETING::PredicateIsFunctional l_isFunctional; // Filter core unit TARGETING::PredicateCTM l_coreUnitFilter(TARGETING::CLASS_UNIT, TARGETING::TYPE_CORE); //Filter functional cores TARGETING::PredicatePostfixExpr l_funcCoreUnitFilter; // core units AND functional l_funcCoreUnitFilter.push(&l_coreUnitFilter).push (&l_isFunctional).And(); // Loop through all the targets, looking for functional core units. TARGETING::TargetRangeFilter l_pFilter( TARGETING::targetService().begin(), TARGETING::targetService().end(), &l_funcCoreUnitFilter); // Assert if no functional cores are found assert(l_pFilter); bool l_copyOnce = true; // Loop through functional cores to get frequency for(; l_pFilter; ++l_pFilter ) { TARGETING::Target * l_pTarget = *l_pFilter; fapi::voltageBucketData_t l_poundVdata = {0}; // Get Parent Chip target const TARGETING::Target * l_pChipTarget = getParentChip(l_pTarget); fapi::Target l_pFapiChipTarget(fapi::TARGET_TYPE_PROC_CHIP, (const_cast<TARGETING::Target*>(l_pChipTarget) )); // Get core number for record number TARGETING::ATTR_CHIP_UNIT_type l_coreNum = l_pTarget->getAttr<TARGETING::ATTR_CHIP_UNIT>(); uint32_t l_record = (uint32_t) MVPD::LRP0 + l_coreNum; // Get #V bucket data l_rc = fapiGetPoundVBucketData(l_pFapiChipTarget, l_record, l_poundVdata); if(l_rc) { TRACFCOMP( g_fapiTd,ERR_MRK"Error getting #V data for HUID:" "0x%08X", l_pTarget->getAttr<TARGETING::ATTR_HUID>()); // Convert fapi returnCode to Error handle l_err = fapiRcToErrl(l_rc); break; } uint32_t l_sysVPDPowerSaveMinFreqMhz = l_poundVdata.PSFreq; TARGETING::ATTR_NOMINAL_FREQ_MHZ_type l_sysNomFreqMhz = l_poundVdata.nomFreq; TARGETING::ATTR_FREQ_CORE_MAX_type l_sysVPDTurboMaxFreqMhz = l_poundVdata.turboFreq; // WOF defines the reserved Fvmin value as ultra turbo TARGETING::ATTR_ULTRA_TURBO_FREQ_MHZ_type l_sysVPDUltraTurboFreqMhz = l_poundVdata.fvminFreq; TRACFCOMP(g_fapiTd,INFO_MRK"Nominal freq is: [0x%08X]. Turbo " "freq is: [0x%08x]. PowerSave freq is: [0x%08X]." " Ultra Turbo is: [0x%08x]", l_sysNomFreqMhz, l_sysVPDTurboMaxFreqMhz, l_sysVPDPowerSaveMinFreqMhz, l_sysVPDUltraTurboFreqMhz); if( true == l_copyOnce) { o_sysNomFreqMhz = l_sysNomFreqMhz; l_minsysVPDTurboMaxFreqMhz = l_sysVPDTurboMaxFreqMhz; l_maxsysVPDPowerSaveMinFreqMhz = l_sysVPDPowerSaveMinFreqMhz; l_minsysVPDUltraTurboFreqMhz = l_sysVPDUltraTurboFreqMhz; l_copyOnce = false; } // frequency is never zero so create error if it is zero. if( (l_sysNomFreqMhz == 0) || (l_sysVPDTurboMaxFreqMhz == 0) || (l_sysVPDPowerSaveMinFreqMhz == 0) ) { TRACFCOMP(g_fapiTd,ERR_MRK"Frequency is zero, " "nominal freq: 0x%04X,turbo freq: 0x%08X", "PowerSave freq is: [0x%08X]", l_sysNomFreqMhz, l_sysVPDTurboMaxFreqMhz, l_sysVPDPowerSaveMinFreqMhz); /*@ * @errortype * @moduleid fapi::MOD_GET_SYS_FREQ * @reasoncode fapi::RC_INVALID_DATA * @userdata1[0:31] Proc HUID * @userdata1[32:63] Nominal frequency * @userdata2[0:31] Max Turbo frequency from VPD * @userdata2[32:63] Min Power Save frequency from VPD * @devdesc Either nominal, max turbo or min power * save frequency for the processor HUID * (userdata1) is zero */ l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, fapi::MOD_GET_SYS_FREQ, fapi::RC_INVALID_DATA, TWO_UINT32_TO_UINT64( l_pTarget->getAttr<TARGETING::ATTR_HUID>(), l_sysNomFreqMhz), TWO_UINT32_TO_UINT64(l_sysVPDTurboMaxFreqMhz, l_sysVPDPowerSaveMinFreqMhz)); // Callout HW as VPD data is incorrect l_err->addHwCallout(l_pTarget, HWAS::SRCI_PRIORITY_HIGH, HWAS::DECONFIG, HWAS::GARD_NULL); break; } // If WOF is enabled, Ultra Turbo frequency should not be zero. // Return 0 for ultra turbo freq if( (fapi::ENUM_ATTR_WOF_ENABLED_ENABLED == l_wofEnabled) && (l_sysVPDUltraTurboFreqMhz == 0) ) { TRACFCOMP(g_fapiTd, ERR_MRK"GetSysFreq: Ultra Turbo frequency is 0"); /*@ * @errortype * @moduleid fapi::MOD_GET_SYS_FREQ * @reasoncode fapi::RC_INVALID_ULTRA_TURBO_FREQ * @userdata1 Proc HUID * @userdata2 Invalid ultra turbo frequency * @devdesc When WOF is enabled, ultra turbo freq * should not be 0 */ l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, fapi::MOD_GET_SYS_FREQ, fapi::RC_INVALID_ULTRA_TURBO_FREQ, l_pTarget->getAttr<TARGETING::ATTR_HUID>(), l_sysVPDUltraTurboFreqMhz); // Callout HW as VPD data is incorrect l_err->addHwCallout(l_pTarget, HWAS::SRCI_PRIORITY_MED, HWAS::NO_DECONFIG, HWAS::GARD_NULL); // log error and keep going errlCommit(l_err,HWPF_COMP_ID); } // Validate nominal frequency. If differs, // create error and stop processing further. if( o_sysNomFreqMhz != l_sysNomFreqMhz ) { TRACFCOMP(g_fapiTd,ERR_MRK "Nominal Frequency:[0x%04X] does not " "match with other core nominal frequency:[0x%04X]", l_sysNomFreqMhz, o_sysNomFreqMhz); /*@ * @errortype * @moduleid fapi::MOD_GET_SYS_FREQ * @reasoncode fapi::RC_INVALID_FREQ * @userdata1 Invalid frequency * @userdata2 Expected frequency * @devdesc Nominal frequency(userdata1) does not match * nominal frequency(userdata2) on other cores. * Should be the same for all chips. */ l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, fapi::MOD_GET_SYS_FREQ, fapi::RC_INVALID_FREQ, l_sysNomFreqMhz, o_sysNomFreqMhz); // Callout HW as VPD data is incorrect l_err->addHwCallout(l_pTarget, HWAS::SRCI_PRIORITY_HIGH, HWAS::DECONFIG, HWAS::GARD_NULL); break; } // Save the min turbo freq if (l_sysVPDTurboMaxFreqMhz < l_minsysVPDTurboMaxFreqMhz) { l_minsysVPDTurboMaxFreqMhz = l_sysVPDTurboMaxFreqMhz; } // Save the max powersave freq if (l_sysVPDPowerSaveMinFreqMhz > l_maxsysVPDPowerSaveMinFreqMhz) { l_maxsysVPDPowerSaveMinFreqMhz = l_sysVPDPowerSaveMinFreqMhz; } // Save the min ultra turbo freq // If WOF is enabled, do not expect to see a zero value. But if // there is a zero value, then return zero. if (l_sysVPDUltraTurboFreqMhz < l_minsysVPDUltraTurboFreqMhz) { l_minsysVPDUltraTurboFreqMhz = l_sysVPDUltraTurboFreqMhz; } } // end for loop if (l_err != NULL) { break; } // Get min turbo freq o_sysVPDTurboMaxFreqMhz = l_minsysVPDTurboMaxFreqMhz; // Get max powersave freq o_sysVPDPowerSaveMinFreqMhz = l_maxsysVPDPowerSaveMinFreqMhz; // Get ultra turbo freq o_sysVPDUltraTurboMinFreqMhz = l_minsysVPDUltraTurboFreqMhz; } while (0); TRACFCOMP(g_fapiTd,EXIT_MRK"o_sysNomFreqMhz: 0x%08X, " "o_sysVPDTurboMaxFreqMhz: 0x%08X, " "o_sysVPDPowerSaveMinFreqMhz: 0x%08X, " "o_sysVPDUltraTurboFreqMhz: 0x%08x", o_sysNomFreqMhz, o_sysVPDTurboMaxFreqMhz, o_sysVPDPowerSaveMinFreqMhz, o_sysVPDUltraTurboMinFreqMhz ); return l_err; }
/*******************Private Methods*********************/ errlHndl_t RtPnor::readFromDevice (uint64_t i_procId, PNOR::SectionId i_section, uint64_t i_offset, size_t i_size, bool i_ecc, void* o_data) const { TRACFCOMP(g_trac_pnor, ENTER_MRK"RtPnor::readFromDevice: i_offset=0x%X, " "i_procId=%d sec=%d size=0x%X ecc=%d", i_offset, i_procId, i_section, i_size, i_ecc); errlHndl_t l_err = nullptr; uint8_t* l_eccBuffer = nullptr; do { const char* l_partitionName = SectionIdToString(i_section); void* l_dataToRead = o_data; size_t l_readSize = i_size; size_t l_readSizePlusECC = (i_size * 9)/8; uint64_t l_offset = i_offset; // if we need to handle ECC, we need to read more if( i_ecc ) { l_eccBuffer = new uint8_t[l_readSizePlusECC](); l_dataToRead = l_eccBuffer; l_readSize = l_readSizePlusECC; l_offset = (i_offset * 9)/8; } int l_rc = 0; if (g_hostInterfaces && g_hostInterfaces->pnor_read) { // get the data from OPAL l_rc = g_hostInterfaces->pnor_read(i_procId, l_partitionName, l_offset, l_dataToRead, l_readSize); if (l_rc < 0) { TRACFCOMP(g_trac_pnor, "RtPnor::readFromDevice: pnor_read" " failed proc:%d, part:%s, offset:0x%X, size:0x%X," " dataPt:0x%X, rc:%d", i_procId, l_partitionName, l_offset, l_readSize, l_dataToRead, l_rc); // prevent hang between ErrlManager and rt_pnor assert(iv_initialized, "RtPnor::readFromDevice: pnor_read returned an error" " during initialization"); /*@ * @errortype * @moduleid PNOR::MOD_RTPNOR_READFROMDEVICE * @reasoncode PNOR::RC_PNOR_READ_FAILED * @userdata1[00:31] rc returned from pnor_read * @userdata1[32:63] section ID * @userdata2[00:31] offset within the section * @userdata2[32:63] size of data read in bytes * @devdesc g_hostInterfaces->pnor_read failed * @custdesc Error accessing system firmware flash */ //@todo Add PNOR callout RTC:116145 l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, PNOR::MOD_RTPNOR_READFROMDEVICE, PNOR::RC_PNOR_READ_FAILED, TWO_UINT32_TO_UINT64(l_rc, i_section), TWO_UINT32_TO_UINT64(l_offset, l_readSize), true); break; } else if( l_rc != static_cast<int>(l_readSize) ) { TRACFCOMP( g_trac_pnor, "RtPnor::readFromDevice: only read 0x%X bytes, expecting 0x%X", l_rc, l_readSize ); if( PNOR::TOC == i_section ) { // we can't know how big the TOC partition is without // reading it so we have to make a request for more // data and then handle a smaller amount getting returned TRACFCOMP( g_trac_pnor, "Ignoring mismatch for TOC" ); } else // everything else should have a known size { // prevent hang between ErrlManager and rt_pnor assert(iv_initialized, "RtPnor::readFromDevice: pnor_read failed to read " "expected amount before rt_pnor initialization"); /*@ * @errortype * @moduleid PNOR::MOD_RTPNOR_READFROMDEVICE * @reasoncode PNOR::RC_WRONG_SIZE_FROM_READ * @userdata1[00:31] section ID * @userdata1[32:63] requested size of read * @userdata2[00:31] requested start offset into flash * @userdata2[32:63] actual amount read * @devdesc Amount of data read from pnor does * not match expected size * @custdesc Error accessing system firmware flash */ l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, PNOR::MOD_RTPNOR_READFROMDEVICE, PNOR::RC_WRONG_SIZE_FROM_READ, TWO_UINT32_TO_UINT64(i_section,l_readSize), TWO_UINT32_TO_UINT64(l_offset,l_rc), true); break; } } } else { TRACFCOMP(g_trac_pnor,"RtPnor::readFromDevice: This version of" " OPAL does not support pnor_read"); // prevent hang between ErrlManager and rt_pnor assert(iv_initialized, "RtPnor::readFromDevice: OPAL version does NOT support" "pnor_read during initialization"); /*@ * @errortype * @moduleid PNOR::MOD_RTPNOR_READFROMDEVICE * @reasoncode PNOR::RC_PNOR_READ_NOT_SUPPORTED * @devdesc g_hostInterfaces->pnor_read not supported * @custdesc Error accessing system firmware flash */ //@todo Add PNOR callout RTC:116145 l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, PNOR::MOD_RTPNOR_READFROMDEVICE, PNOR::RC_PNOR_READ_NOT_SUPPORTED, 0,0,true); break; } // remove the ECC data if( i_ecc ) { TRACFCOMP(g_trac_pnor, "RtPnor::readFromDevice: removing ECC..."); // remove the ECC and fix the original data if it is broken size_t l_eccSize = (l_rc/9)*8; l_eccSize = std::min( l_eccSize, i_size ); PNOR::ECC::eccStatus ecc_stat = PNOR::ECC::removeECC(reinterpret_cast<uint8_t*>(l_dataToRead), reinterpret_cast<uint8_t*>(o_data), l_eccSize); //logical size of read data // create an error if we couldn't correct things if( ecc_stat == PNOR::ECC::UNCORRECTABLE ) { TRACFCOMP(g_trac_pnor,"RtPnor::readFromDevice>" " Uncorrectable ECC error : chip=%d,offset=0x%.X", i_procId, i_offset ); // prevent hang between ErrlManager and rt_pnor assert(iv_initialized, "RtPnor::readFromDevice: UNCORRECTABLE_ECC encountered" " during initialization"); /*@ * @errortype * @moduleid PNOR::MOD_RTPNOR_READFROMDEVICE * @reasoncode PNOR::RC_UNCORRECTABLE_ECC * @devdesc UNCORRECTABLE ECC */ //@todo Add PNOR callout RTC:116145 l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, PNOR::MOD_RTPNOR_READFROMDEVICE, PNOR::RC_UNCORRECTABLE_ECC, 0, 0, true); break; } // found an error so we need to fix something else if( ecc_stat != PNOR::ECC::CLEAN ) { TRACFCOMP(g_trac_pnor,"RtPnor::readFromDevice>" "Correctable ECC error : chip=%d, offset=0x%.X", i_procId, i_offset ); if (g_hostInterfaces && g_hostInterfaces->pnor_write) { //need to write good data back to PNOR int l_rc = g_hostInterfaces->pnor_write(i_procId, l_partitionName,l_offset, l_dataToRead,l_readSize); if (l_rc != static_cast<int>(l_readSize)) { TRACFCOMP(g_trac_pnor, "RtPnor::readFromDevice> Error" " writing corrected data back to device"); // prevent hang between ErrlManager and rt_pnor assert(iv_initialized, "RtPnor::readFromDevice: pnor_write returned an" " error during initialization"); /*@ * @errortype * @moduleid PNOR::MOD_RTPNOR_READFROMDEVICE * @reasoncode PNOR::RC_PNOR_WRITE_FAILED * @userdata1 rc returned from pnor_write * @userdata2 Expected size of write * @devdesc error writing corrected data back to PNOR * @custdesc Error accessing system firmware flash */ l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, PNOR::MOD_RTPNOR_READFROMDEVICE, PNOR::RC_PNOR_WRITE_FAILED, l_rc, l_readSize, true); errlCommit(l_err, PNOR_COMP_ID); } } } } } while(0); if( l_eccBuffer ) { delete[] l_eccBuffer; } TRACFCOMP(g_trac_pnor, EXIT_MRK"RtPnor::readFromDevice" ); return l_err; }
/*******************Private Methods*********************/ errlHndl_t RtPnor::readFromDevice (uint64_t i_procId, PNOR::SectionId i_section, uint64_t i_offset, size_t i_size, bool i_ecc, void* o_data) { TRACFCOMP(g_trac_pnor, ENTER_MRK"RtPnor::readFromDevice: i_offset=0x%X, " "i_procId=%d sec=%d size=0x%X ecc=%d", i_offset, i_procId, i_section, i_size, i_ecc); errlHndl_t l_err = NULL; uint8_t* l_eccBuffer = NULL; do { const char* l_partitionName = cv_EYECATCHER[i_section]; void* l_dataToRead = o_data; size_t l_readSize = i_size; size_t l_readSizePlusECC = (i_size * 9)/8; uint64_t l_offset = i_offset; // if we need to handle ECC, we need to read more if( i_ecc ) { l_eccBuffer = new uint8_t[l_readSizePlusECC](); l_dataToRead = l_eccBuffer; l_readSize = l_readSizePlusECC; l_offset = (i_offset * 9)/8; } int l_rc = 0; if (g_hostInterfaces && g_hostInterfaces->pnor_read) { // get the data from OPAL l_rc = g_hostInterfaces->pnor_read(i_procId, l_partitionName, l_offset, l_dataToRead, l_readSize); if (l_rc < 0) { TRACFCOMP(g_trac_pnor, "RtPnor::readFromDevice: pnor_read" " failed proc:%d, part:%s, offset:0x%X, size:0x%X," " dataPt:0x%X, rc:%d", i_procId, l_partitionName, l_offset, l_readSize, l_dataToRead, l_rc); /*@ * @errortype * @moduleid PNOR::MOD_RTPNOR_READFROMDEVICE * @reasoncode PNOR::RC_PNOR_READ_FAILED * @userdata1[00:31] rc returned from pnor_read * @userdata1[32:63] section ID * @userdata2[00:31] offset within the section * @userdata2[32:63] size of data read in bytes * @devdesc g_hostInterfaces->pnor_read failed * @custdesc Error accessing system firmware flash */ //@todo Add PNOR callout RTC:116145 l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, PNOR::MOD_RTPNOR_READFROMDEVICE, PNOR::RC_PNOR_READ_FAILED, TWO_UINT32_TO_UINT64(l_rc, i_section), TWO_UINT32_TO_UINT64(l_offset, l_readSize), true); break; } else if( l_rc != static_cast<int>(l_readSize) ) { TRACFCOMP( g_trac_pnor, "RtPnor::readFromDevice: only read 0x%X bytes, expecting 0x%X", l_rc, l_readSize ); } } else { TRACFCOMP(g_trac_pnor,"RtPnor::readFromDevice: This version of" " OPAL does not support pnor_read"); /*@ * @errortype * @moduleid PNOR::MOD_RTPNOR_READFROMDEVICE * @reasoncode PNOR::RC_PNOR_READ_NOT_SUPPORTED * @devdesc g_hostInterfaces->pnor_read not supported * @custdesc Error accessing system firmware flash */ //@todo Add PNOR callout RTC:116145 l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, PNOR::MOD_RTPNOR_READFROMDEVICE, PNOR::RC_PNOR_READ_NOT_SUPPORTED, 0,0,true); break; } // remove the ECC data if( i_ecc ) { TRACFCOMP(g_trac_pnor, "RtPnor::readFromDevice: removing ECC..."); // remove the ECC and fix the original data if it is broken PNOR::ECC::eccStatus ecc_stat = PNOR::ECC::removeECC(reinterpret_cast<uint8_t*>(l_dataToRead), reinterpret_cast<uint8_t*>(o_data), l_rc); //actual size of read data // create an error if we couldn't correct things if( ecc_stat == PNOR::ECC::UNCORRECTABLE ) { TRACFCOMP(g_trac_pnor,"RtPnor::readFromDevice>" " Uncorrectable ECC error : chip=%d,offset=0x%.X", i_procId, i_offset ); /*@ * @errortype * @moduleid PNOR::MOD_RTPNOR_READFROMDEVICE * @reasoncode PNOR::RC_UNCORRECTABLE_ECC * @devdesc UNCORRECTABLE ECC */ //@todo Add PNOR callout RTC:116145 l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, PNOR::MOD_RTPNOR_READFROMDEVICE, PNOR::RC_UNCORRECTABLE_ECC, 0, 0, true); break; } // found an error so we need to fix something else if( ecc_stat != PNOR::ECC::CLEAN ) { TRACFCOMP(g_trac_pnor,"RtPnor::readFromDevice>" "Correctable ECC error : chip=%d, offset=0x%.X", i_procId, i_offset ); if (g_hostInterfaces && g_hostInterfaces->pnor_write) { //need to write good data back to PNOR int l_rc = g_hostInterfaces->pnor_write(i_procId, l_partitionName,l_offset, l_dataToRead,l_readSize); if (l_rc != static_cast<int>(l_readSize)) { TRACFCOMP(g_trac_pnor, "RtPnor::readFromDevice> Error" " writing corrected data back to device"); /*@ * @errortype * @moduleid PNOR::MOD_RTPNOR_READFROMDEVICE * @reasoncode PNOR::RC_PNOR_WRITE_FAILED * @userdata1 rc returned from pnor_write * @userdata2 Expected size of write * @devdesc error writing corrected data back to PNOR * @custdesc Error accessing system firmware flash */ l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, PNOR::MOD_RTPNOR_READFROMDEVICE, PNOR::RC_PNOR_WRITE_FAILED, l_rc, l_readSize, true); errlCommit(l_err, PNOR_COMP_ID); } } } } } while(0); if( l_eccBuffer ) { delete[] l_eccBuffer; } TRACFCOMP(g_trac_pnor, EXIT_MRK"RtPnor::readFromDevice" ); return l_err; }
errlHndl_t fsiScomPerformOp(DeviceFW::OperationType i_opType, TARGETING::Target* i_target, void* io_buffer, size_t& io_buflen, int64_t i_accessType, va_list i_args) { errlHndl_t l_err = NULL; uint64_t l_scomAddr = va_arg(i_args,uint64_t); ioData6432 scratchData; uint32_t l_command = 0; uint32_t l_status = 0; bool need_unlock = false; size_t op_size = sizeof(uint32_t); mutex_t* l_mutex = NULL; do{ if( io_buflen != sizeof(uint64_t) ) { TRACFCOMP( g_trac_fsiscom, ERR_MRK "fsiScomPerformOp> Invalid data length : io_buflen=%d", io_buflen ); /*@ * @errortype * @moduleid FSISCOM::MOD_FSISCOM_PERFORMOP * @reasoncode FSISCOM::RC_INVALID_LENGTH * @userdata1 SCOM Address * @userdata2 Data Length * @devdesc fsiScomPerformOp> Invalid data length (!= 8 bytes) * @custdesc A problem occurred during the IPL of the system: * Invalid data length for a SCOM operation. */ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, FSISCOM::MOD_FSISCOM_PERFORMOP, FSISCOM::RC_INVALID_LENGTH, l_scomAddr, TO_UINT64(io_buflen)); l_err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE, HWAS::SRCI_PRIORITY_LOW ); ERRORLOG::ErrlUserDetailsTarget(i_target,"SCOM Target"). addToLog(l_err); break; } if( (l_scomAddr & 0xFFFFFFFF80000000) != 0) { TRACFCOMP( g_trac_fsiscom, ERR_MRK "fsiScomPerformOp> Address contains more than 31 bits : l_scomAddr=0x%.16X", l_scomAddr ); /*@ * @errortype * @moduleid FSISCOM::MOD_FSISCOM_PERFORMOP * @reasoncode FSISCOM::RC_INVALID_ADDRESS * @userdata1 SCOM Address * @userdata2 Target HUID * @devdesc fsiScomPerformOp> Address contains * more than 31 bits. * @custdesc A problem occurred during the IPL of the system: * Invalid address on a SCOM operation. */ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, FSISCOM::MOD_FSISCOM_PERFORMOP, FSISCOM::RC_INVALID_ADDRESS, l_scomAddr, TARGETING::get_huid(i_target)); l_err->addProcedureCallout( HWAS::EPUB_PRC_HB_CODE, HWAS::SRCI_PRIORITY_LOW ); ERRORLOG::ErrlUserDetailsTarget(i_target,"SCOM Target"). addToLog(l_err); break; } l_command = static_cast<uint32_t>(l_scomAddr & 0x000000007FFFFFFF); // use the chip-specific mutex attribute l_mutex = i_target->getHbMutexAttr<TARGETING::ATTR_FSI_SCOM_MUTEX>(); if(i_opType == DeviceFW::WRITE) { memcpy(&(scratchData.data64), io_buffer, 8); TRACUCOMP( g_trac_fsiscom, "fsiScomPerformOp> Write(l_scomAddr=0x%X, l_data0=0x%X, l_data1=0x%X)", l_scomAddr, scratchData.data32_0, scratchData.data32_1); // atomic section >> mutex_lock(l_mutex); need_unlock = true; //write bits 0-31 to data0 l_err = DeviceFW::deviceOp( DeviceFW::WRITE, i_target, &scratchData.data32_0, op_size, DEVICE_FSI_ADDRESS(DATA0_REG)); if(l_err) { break; } //write bits 32-63 to data1 l_err = DeviceFW::deviceOp( DeviceFW::WRITE, i_target, &scratchData.data32_1, op_size, DEVICE_FSI_ADDRESS(DATA1_REG)); if(l_err) { break; } //write to FSI2PIB command reg starts write operation //bit 0 high => write command l_command = 0x80000000 | l_command; l_err = DeviceFW::deviceOp( DeviceFW::WRITE, i_target, &l_command, op_size, DEVICE_FSI_ADDRESS(COMMAND_REG)); if(l_err) { break; } //check status reg to see result l_err = DeviceFW::deviceOp( DeviceFW::READ, i_target, &l_status, op_size, DEVICE_FSI_ADDRESS(STATUS_REG)); if(l_err) { break; } // Check the status reg for errors if( (l_status & PIB_ERROR_BITS) // PCB/PIB Errors || (l_status & PIB_ABORT_BIT) ) // PIB Abort { TRACFCOMP( g_trac_fsiscom, ERR_MRK"fsiScomPerformOp:Write: PCB/PIB error received: l_status=0x%X)", l_status); /*@ * @errortype * @moduleid FSISCOM::MOD_FSISCOM_PERFORMOP * @reasoncode FSISCOM::RC_WRITE_ERROR * @userdata1 SCOM Addr * @userdata2[00:31] Target HUID * @userdata2[32:63] SCOM Status Reg * @devdesc fsiScomPerformOp> Error returned * from SCOM Engine after write * @custdesc A problem occurred during the IPL of the system: * Error returned from SCOM engine after write. */ l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, FSISCOM::MOD_FSISCOM_PERFORMOP, FSISCOM::RC_WRITE_ERROR, l_scomAddr, TWO_UINT32_TO_UINT64( TARGETING::get_huid(i_target), l_status)); // call common error handler to do callouts and recovery pib_error_handler( i_target, l_err, l_status, l_scomAddr ); //Grab the PIB2OPB Status reg for a XSCOM Block error if( (l_status & 0x00007000) == 0x00001000 ) //piberr=001 { //@todo: Switch to external FSI FFDC interfaces RTC:35064 TARGETING::Target* l_master = NULL; TARGETING::targetService(). masterProcChipTargetHandle(l_master); uint64_t scomdata = 0; size_t scomsize = sizeof(uint64_t); errlHndl_t l_err2 = DeviceFW::deviceOp( DeviceFW::READ, l_master, &scomdata, scomsize, DEVICE_XSCOM_ADDRESS(0x00020001)); if( l_err2 ) { delete l_err2; } else { TRACFCOMP( g_trac_fsiscom, "PIB2OPB Status = %.16X", scomdata ); } } break; } // atomic section << need_unlock = false; mutex_unlock(l_mutex); } else if(i_opType == DeviceFW::READ) { TRACUCOMP( g_trac_fsiscom, "fsiScomPerformOp: Read(l_scomAddr=0x%.8X)", l_scomAddr); // atomic section >> mutex_lock(l_mutex); need_unlock = true; //write to FSI2PIB command reg starts read operation // bit 0 low -> read command l_err = DeviceFW::deviceOp( DeviceFW::WRITE, i_target, &l_command, op_size, DEVICE_FSI_ADDRESS(COMMAND_REG)); if(l_err) { break; } //check ststus reg to see result l_err = DeviceFW::deviceOp( DeviceFW::READ, i_target, &l_status, op_size, DEVICE_FSI_ADDRESS(STATUS_REG)); if(l_err) { break; } // Check the status reg for errors if( (l_status & PIB_ERROR_BITS) // PCB/PIB Errors || (l_status & PIB_ABORT_BIT) ) // PIB Abort { TRACFCOMP( g_trac_fsiscom, ERR_MRK"fsiScomPerformOp:Read: PCB/PIB error received: l_status=0x%0.8X)", l_status); /*@ * @errortype * @moduleid FSISCOM::MOD_FSISCOM_PERFORMOP * @reasoncode FSISCOM::RC_READ_ERROR * @userdata1 SCOM Addr * @userdata2[00:31] Target HUID * @userdata2[32:63] SCOM Status Reg * @devdesc fsiScomPerformOp> Error returned from SCOM Engine after read. * @custdesc A problem occurred during the IPL of the system: * Error returned from SCOM engine after read. */ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, FSISCOM::MOD_FSISCOM_PERFORMOP, FSISCOM::RC_READ_ERROR, l_scomAddr, TWO_UINT32_TO_UINT64( TARGETING::get_huid(i_target), l_status)); // call common error handler to do callouts and recovery pib_error_handler( i_target, l_err, l_status, l_scomAddr ); break; } //read bits 0-31 to data0 l_err = DeviceFW::deviceOp( DeviceFW::READ, i_target, &scratchData.data32_0, op_size, DEVICE_FSI_ADDRESS(DATA0_REG)); if(l_err) { break; } //read bits 32-63 to data1 l_err = DeviceFW::deviceOp( DeviceFW::READ, i_target, &scratchData.data32_1, op_size, DEVICE_FSI_ADDRESS(DATA1_REG)); if(l_err) { break; } // atomic section << need_unlock = false; mutex_unlock(l_mutex); TRACUCOMP( g_trac_fsiscom, "fsiScomPerformOp: Read: l_scomAddr=0x%X, l_data0=0x%X, l_data1=0x%X", l_scomAddr, scratchData.data32_0, scratchData.data32_1); memcpy(io_buffer, &(scratchData.data64), 8); } else { TRACFCOMP( g_trac_fsiscom, ERR_MRK"fsiScomPerformOp:Unsupported Operation Type: i_opType=%d)", i_opType); /*@ * @errortype * @moduleid FSISCOM::MOD_FSISCOM_PERFORMOP * @reasoncode FSISCOM::RC_INVALID_OPTYPE * @userdata1[0:31] Operation Type (i_opType) : 0=READ, 1=WRITE * @userdata1[32:64] Input scom address * @userdata2 Target HUID * @devdesc fsiScomPerformOp> Unsupported Operation Type specified * @custdesc A problem occurred during the IPL of the system: * Unsupported SCOM operation type. */ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, FSISCOM::MOD_FSISCOM_PERFORMOP, FSISCOM::RC_INVALID_OPTYPE, TWO_UINT32_TO_UINT64(i_opType, l_scomAddr), TARGETING::get_huid(i_target), true /*SW error*/); //Add this target to the FFDC ERRORLOG::ErrlUserDetailsTarget(i_target,"SCOM Target"). addToLog(l_err); break; } }while(0); if( need_unlock && l_mutex ) { mutex_unlock(l_mutex); } return l_err; }
//****************************************************************************** //TodSvc::setActiveMdmtForResetBackup //****************************************************************************** errlHndl_t TodSvc::setActiveMdmtForResetBackup( const p9_tod_setup_tod_sel i_activeConfig) { TOD_ENTER("setActiveMdmtForResetBackup"); errlHndl_t l_errHdl = NULL; //While doing a resetBackup it was found that in memory copy of active //topology is not present, (system has done a RR ) //In order to ensure redundancy of processor and oscillator source on the //backup topology we needed to have the copy of active topology in memory. //However we may not need to recreate the complete active topology from //the persistant topology information file. //It would be just sufficient if we have the todControls built and MDMT set do{ l_errHdl = TOD::buildTodDrawers(i_activeConfig); if ( l_errHdl ) { TOD_ERR("Failed to build TOD drawers for %s", (TOD::TodSvcUtil:: topologyTypeToString(i_activeConfig))); break; } TARGETING::Target* l_primaryMdmt = NULL; TARGETING::Target* l_secondaryMdmt = NULL; //Read the HW to get the configured MDMT's l_errHdl = TOD::getConfiguredMdmt(l_primaryMdmt, l_secondaryMdmt); if ( l_errHdl ) { TOD_ERR("Failed to get the configured MDMTs "); break; } TARGETING::Target* l_mdmtOnActiveTopology = NULL; l_mdmtOnActiveTopology = ( i_activeConfig == TOD_PRIMARY )? l_primaryMdmt : l_secondaryMdmt; if ( !l_mdmtOnActiveTopology ) //Big problem--This should not happen { TOD_ERR("TOD HW logic is already running but we cannot locate" "MDMT for the %s , that is active", (TOD::TodSvcUtil:: topologyTypeToString(i_activeConfig))); /*@ * @errortype * @moduleid TOD_MDMT_TOPOLOGY * @reasoncode TOD_NO_VALID_MDMT_FOUND * @userdata1 EMOD_TOD_SET_ACTIVE_MDMT * @userdata2 Topology type on which MDMT was searched * @devdesc Error: Could not find MDMT on active topology * even though TOD HW logic is running * @custdesc Host failed to boot because there was a problem * configuring Time Of Day on the Host processors */ l_errHdl = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_INFORMATIONAL, TOD_MDMT_TOPOLOGY, TOD_NO_VALID_MDMT_FOUND, EMOD_TOD_SET_ACTIVE_MDMT, i_activeConfig); break; } //We have the valid MDMT target now, find the TodProc object //corresponding to it and also figure out the TodDrawer object to //which this processor belongs //To do so get the TodProc object whose HUID matches with the HUID //of the active topology's MDMT, and also get the TOD drawer to which //this TodProc object belongs TodDrawer* l_masterDrawer = NULL; TodProc* l_masterProc = NULL; std::list<TodDrawer*> l_drawerList; TOD::getDrawers(i_activeConfig, l_drawerList); bool l_drawerFound = false; for(std::list<TodDrawer*>::iterator l_drawerItr = l_drawerList.begin(); ((l_drawerItr != l_drawerList.end()) && !l_drawerFound); ++l_drawerItr) { const std::list<TodProc*>& l_procsList = (*l_drawerItr)->getProcs(); for(std::list<TodProc*>::const_iterator l_procItr = l_procsList.begin(); ((l_procItr != l_procsList.end()) && !l_drawerFound); ++l_procItr) { if ( (*l_procItr)->getTarget() == l_mdmtOnActiveTopology) { l_masterProc = *l_procItr; l_masterDrawer = *l_drawerItr; l_drawerFound = true; } } } if ( !l_masterProc || !l_masterDrawer ) { //This should never happen unless we have goofed up big time TOD_ERR("Could not find TOD objects for the configured " "MDMT 0x%08X on %s", GETHUID(l_mdmtOnActiveTopology), (TOD::TodSvcUtil:: topologyTypeToString(i_activeConfig))); //FIX_ME_BEFORE_PRODUCTION_Q1 bool l_masterProcNotFound = ( !l_masterProc )? true : false; bool l_masterDrawerNotFound = ( !l_masterDrawer )? true : false; /*@ * @errortype * @moduleid TOD_FIND_MASTER_PROC * @reasoncode TOD_MASTER_TARGET_NOT_FOUND * @userdata1[32:64] 1 = Master proc was not found , zero otherwise * @userdata1[32:63] 1 = Master drawer was not found, zero otherwise * @userdata2[0:31] EMOD_TOD_SET_ACTIVE_MDMT * @userdata2[32:64] Active topology * @devdesc Either processor or drawer object was not found for * the MDMT found by reading the processor registers. * @custdesc Service Processor Firmware encountered an internal * error */ l_errHdl = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_INFORMATIONAL, TOD_FIND_MASTER_PROC, TOD_MASTER_TARGET_NOT_FOUND, TWO_UINT32_TO_UINT64( l_masterProcNotFound, l_masterDrawerNotFound), TWO_UINT32_TO_UINT64( EMOD_TOD_SET_ACTIVE_MDMT, i_activeConfig)); break; } //Now we have the all the objects required to set the MDMT (void) TOD::setMdmtOfActiveConfig( i_activeConfig, l_masterProc, l_masterDrawer); }while(0); TOD_EXIT(); return l_errHdl; }
//************************************************************************** // FREQVOLTSVC::getSysFreq //************************************************************************** errlHndl_t getSysFreq( uint32_t & o_sysVPDPowerSaveMinFreqMhz, TARGETING::ATTR_NOMINAL_FREQ_MHZ_type & o_sysNomFreqMhz, TARGETING::ATTR_FREQ_CORE_MAX_type & o_sysVPDTurboMaxFreqMhz) { uint32_t l_minsysVPDTurboMaxFreqMhz = 0; uint32_t l_maxsysVPDPowerSaveMinFreqMhz = 0; fapi::ReturnCode l_rc; errlHndl_t l_err = NULL; do { o_sysNomFreqMhz = 0; o_sysVPDTurboMaxFreqMhz = 0; o_sysVPDPowerSaveMinFreqMhz = 0; //Filter functional unit TARGETING::PredicateIsFunctional l_isFunctional; // Filter core unit TARGETING::PredicateCTM l_coreUnitFilter(TARGETING::CLASS_UNIT, TARGETING::TYPE_CORE); //Filter functional cores TARGETING::PredicatePostfixExpr l_funcCoreUnitFilter; // core units AND functional l_funcCoreUnitFilter.push(&l_coreUnitFilter).push (&l_isFunctional).And(); // Loop through all the targets, looking for functional core units. TARGETING::TargetRangeFilter l_pFilter( TARGETING::targetService().begin(), TARGETING::targetService().end(), &l_funcCoreUnitFilter); // Assert if no functional cores are found assert(l_pFilter); bool l_copyOnce = true; // Loop through functional cores to get frequency for(; l_pFilter; ++l_pFilter ) { TARGETING::Target * l_pTarget = *l_pFilter; fapi::voltageBucketData_t l_poundVdata = {0}; // Get Parent Chip target const TARGETING::Target * l_pChipTarget = getParentChip(l_pTarget); // Get core number for record number TARGETING::ATTR_CHIP_UNIT_type l_coreNum = l_pTarget->getAttr<TARGETING::ATTR_CHIP_UNIT>(); uint32_t l_record = (uint32_t) MVPD::LRP0 + l_coreNum; // Get #V bucket data l_rc = fapiGetPoundVBucketData(l_pChipTarget, l_record, l_poundVdata); if(l_rc) { TRACFCOMP( g_fapiTd,ERR_MRK"Error getting #V data for HUID:" "0x%08X", l_pTarget->getAttr<TARGETING::ATTR_HUID>()); // Convert fapi returnCode to Error handle l_err = fapiRcToErrl(l_rc); break; } uint32_t l_sysVPDPowerSaveMinFreqMhz = l_poundVdata.PSFreq; TARGETING::ATTR_NOMINAL_FREQ_MHZ_type l_sysNomFreqMhz = l_poundVdata.nomFreq; TARGETING::ATTR_FREQ_CORE_MAX_type l_sysVPDTurboMaxFreqMhz = l_poundVdata.turboFreq; TRACFCOMP(g_fapiTd,INFO_MRK"Nominal freq is: [0x%08X]. Turbo " "freq is: [0x%08x]. PowerSave freq is: [0x%08X]", l_sysNomFreqMhz, l_sysVPDTurboMaxFreqMhz, l_sysVPDPowerSaveMinFreqMhz ); if( true == l_copyOnce) { o_sysNomFreqMhz = l_sysNomFreqMhz; l_minsysVPDTurboMaxFreqMhz = l_sysVPDTurboMaxFreqMhz; l_maxsysVPDPowerSaveMinFreqMhz = l_sysVPDPowerSaveMinFreqMhz; l_copyOnce = false; } // frequency is never zero so create error if it is zero. if( (l_sysNomFreqMhz == 0) || (l_sysVPDTurboMaxFreqMhz == 0) || (l_sysVPDPowerSaveMinFreqMhz == 0) ) { TRACFCOMP(g_fapiTd,ERR_MRK"Frequency is zero, " "nominal freq: 0x%04X,turbo freq: 0x%08X", "PowerSave freq is: [0x%08X]", l_sysNomFreqMhz, l_sysVPDTurboMaxFreqMhz, l_sysVPDPowerSaveMinFreqMhz); /*@ * @errortype * @moduleid fapi::MOD_GET_SYS_FREQ * @reasoncode fapi::RC_INVALID_DATA * @userdata1[0:31] Proc HUID * @userdata1[32:63] Nominal frequency * @userdata2[0:31] Max Turbo frequency from VPD * @userdata2[32:63] Min Power Save frequency from VPD * @devdesc Either nominal, max turbo or min power * save frequency for the processor HUID * (userdata1) is zero */ l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, fapi::MOD_GET_SYS_FREQ, fapi::RC_INVALID_DATA, TWO_UINT32_TO_UINT64( l_pTarget->getAttr<TARGETING::ATTR_HUID>(), l_sysNomFreqMhz), TWO_UINT32_TO_UINT64(l_sysVPDTurboMaxFreqMhz, l_sysVPDPowerSaveMinFreqMhz)); // Callout HW as VPD data is incorrect l_err->addHwCallout(l_pTarget, HWAS::SRCI_PRIORITY_HIGH, HWAS::DECONFIG, HWAS::GARD_NULL); break; } // Validate nominal frequency. If differs, // create error and stop processing further. if( o_sysNomFreqMhz != l_sysNomFreqMhz ) { TRACFCOMP(g_fapiTd,ERR_MRK "Nominal Frequency:[0x%04X] does not " "match with other core nominal frequency:[0x%04X]", l_sysNomFreqMhz, o_sysNomFreqMhz); /*@ * @errortype * @moduleid fapi::MOD_GET_SYS_FREQ * @reasoncode fapi::RC_INVALID_FREQ * @userdata1 Invalid frequency * @userdata2 Expected frequency * @devdesc Nominal frequency(userdata1) does not match * nominal frequency(userdata2) on other cores. * Should be the same for all chips. */ l_err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, fapi::MOD_GET_SYS_FREQ, fapi::RC_INVALID_FREQ, l_sysNomFreqMhz, o_sysNomFreqMhz); // Callout HW as VPD data is incorrect l_err->addHwCallout(l_pTarget, HWAS::SRCI_PRIORITY_HIGH, HWAS::DECONFIG, HWAS::GARD_NULL); break; } // Save the min turbo freq if (l_sysVPDTurboMaxFreqMhz < l_minsysVPDTurboMaxFreqMhz) { l_minsysVPDTurboMaxFreqMhz = l_sysVPDTurboMaxFreqMhz; } // Save the max powersave freq if (l_sysVPDPowerSaveMinFreqMhz > l_maxsysVPDPowerSaveMinFreqMhz) { l_maxsysVPDPowerSaveMinFreqMhz = l_sysVPDPowerSaveMinFreqMhz; } } // end for loop if (l_err != NULL) { break; } // Get min turbo freq o_sysVPDTurboMaxFreqMhz = l_minsysVPDTurboMaxFreqMhz; // Get max powersave freq o_sysVPDPowerSaveMinFreqMhz = l_maxsysVPDPowerSaveMinFreqMhz; } while (0); TRACFCOMP(g_fapiTd,EXIT_MRK"o_sysNomFreqMhz: 0x%08X, " "o_sysVPDTurboMaxFreqMhz: 0x%08X, " "o_sysVPDPowerSaveMinFreqMhz: 0x%08X", o_sysNomFreqMhz, o_sysVPDTurboMaxFreqMhz, o_sysVPDPowerSaveMinFreqMhz ); return l_err; }