/////////////////////////////////////////////////////////////////////////////// // ErrlManager::ackErrLogInPnor() /////////////////////////////////////////////////////////////////////////////// bool ErrlManager::ackErrLogInPnor( uint32_t i_errEid ) { TRACFCOMP( g_trac_errl, ENTER_MRK"ackErrLogInPnor(%.8x)", i_errEid); bool rc = true; // look for an un-ACKed log that matches this eid uint32_t i; for (i = 0; i < iv_maxErrlInPnor; i++) { if (!isSlotEmpty(i) && !isSlotACKed(i)) { uint32_t l_eid = readEidFromFlattened(i); if (l_eid == i_errEid) { TRACDCOMP( g_trac_errl, INFO_MRK"ackErrLogInPnor: match in slot %d", i); setACKInFlattened(i); break; } } } // for // if we made it through the loop w/out breaking early if (i == iv_maxErrlInPnor) { //could not find the errorlog to mark for acknowledgment TRACDCOMP( g_trac_errl, ERR_MRK"ackErrLogInPnor failed to find the error log" ); rc = false; } TRACFCOMP( g_trac_errl, EXIT_MRK"ackErrLogInPnor returning %s", rc ? "true" : "false"); return rc; } // ackErrLogInPnor
/////////////////////////////////////////////////////////////////////////////// // ErrlManager::incrementPnorOpenSlot() /////////////////////////////////////////////////////////////////////////////// bool ErrlManager::incrementPnorOpenSlot() { uint32_t initialSlot = iv_pnorOpenSlot; // starting slot do { iv_pnorOpenSlot++; if (iv_pnorOpenSlot == iv_maxErrlInPnor) { // wrap iv_pnorOpenSlot = 0; } } while ( !isSlotEmpty(iv_pnorOpenSlot) && !isSlotACKed(iv_pnorOpenSlot) && (iv_pnorOpenSlot != initialSlot)); // if we got a different slot, return true; else false - no open slots return (iv_pnorOpenSlot != initialSlot); } // incrementPnorOpenSlot
// ------------------------------------------------------------------ // setupPnorInfo // ------------------------------------------------------------------ void ErrlManager::setupPnorInfo() { TRACFCOMP( g_trac_errl, ENTER_MRK"setupPnorInfo" ); do { // Get SPD PNOR section info from PNOR RP PNOR::SectionInfo_t info; errlHndl_t err = PNOR::getSectionInfo( PNOR::HB_ERRLOGS, info ); if (err) { TRACFCOMP( g_trac_errl, INFO_MRK"setupPnorInfo getSectionInfo failed"); assert(err == NULL); break; } TRACFCOMP( g_trac_errl, INFO_MRK"setupPnorInfo sectionInfo id %d name \"%s\" size %d", info.id, info.name, info.size ); // Set the globals appropriately iv_pnorAddr = reinterpret_cast<char *> (info.vaddr); iv_maxErrlInPnor = info.size / PNOR_ERROR_LENGTH; TRACFCOMP( g_trac_errl, INFO_MRK"setupPnorInfo iv_pnorAddr %p maxErrlInPnor %d", iv_pnorAddr, iv_maxErrlInPnor ); // initial value, in case PNOR is empty - start at this end slot // so that our first save will increment and wrap correctly iv_pnorOpenSlot = (iv_maxErrlInPnor - 1); // walk thru memory, finding error logs and determine the highest ID uint32_t l_maxId = 0; for (uint32_t i = 0; i < iv_maxErrlInPnor; i++) { if (!isSlotEmpty(i)) { uint32_t l_id = readEidFromFlattened(i); // If id is not from HB (0x9XXXXXXX) grab plid instead if ( (l_id & FIRST_BYTE_ERRLOG) != ERRLOG_PLID_BASE ) { l_id = readPlidFromFlattened(i); } if (l_id > l_maxId ) { l_maxId = l_id; // set this - start at this 'max' slot so that our first // save will increment correctly iv_pnorOpenSlot = i; } // also check if it's ACKed or not if (!isSlotACKed(i)) { TRACFCOMP( g_trac_errl, INFO_MRK"setupPnorInfo slot %d eid %.8X was not ACKed.", i, l_id); #ifdef CONFIG_BMC_IPMI // for IPMI systems, unflatten to send down to the BMC err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, 0,0); char *l_errlAddr = iv_pnorAddr + (PNOR_ERROR_LENGTH * i); uint64_t rc = err->unflatten(l_errlAddr, PNOR_ERROR_LENGTH); if (rc != 0) { // unflatten didn't work, nothing we can do TRACFCOMP( g_trac_errl, ERR_MRK"setupPnorInfo unflatten failed on slot %d eid %.8X.", i, l_id); } else { if (iv_isIpmiEnabled) { // convert to SEL/eSEL and send to BMC over IPMI sendErrLogToBmc(err); delete err; } else { TRACFCOMP( g_trac_errl, INFO_MRK"setupPnorInfo pushing slot %d eid %.8X to iv_errList.", i, l_id); // Pair with IPMI flag to add to the errlList // so that it'll get sent down when IPMI is up ErrlFlagPair_t l_pair(err, IPMI_FLAG); iv_errlList.push_back(l_pair); } } #else // for FSP system, this shouldn't ever happen. #endif setACKInFlattened(i); } // not ACKed } // not empty } // for // bump the current eid to 1 past the max eid found while (!__sync_bool_compare_and_swap(&iv_currLogId, iv_currLogId, (iv_currLogId & ERRLOG_PLID_BASE_MASK) + (l_maxId & ERRLOG_PLID_MASK) + 1)); TRACFCOMP( g_trac_errl, INFO_MRK"setupPnorInfo reseting LogId 0x%X", iv_currLogId); // if error(s) came in before PNOR was ready, // the error log(s) would be on this list. save now. ErrlListItr_t it = iv_errlList.begin(); while(it != iv_errlList.end()) { // Check if PNOR processing is needed if (_isFlagSet(*it, PNOR_FLAG)) { //ACK it if no one is there to receive bool l_savedToPnor = saveErrLogToPnor(it->first); // check if we actually saved the msg to PNOR if (l_savedToPnor) { // Mark PNOR processing complete _clearFlag(*it, PNOR_FLAG); _updateErrlListIter(it); } else { // still couldn't save it (PNOR maybe full) so // it's still on the list. break; // get out of this while loop. } } else { ++it; } } } while (0); TRACFCOMP( g_trac_errl, EXIT_MRK"setupPnorInfo"); } // setupPnorInfo
// ------------------------------------------------------------------ // setupPnorInfo // ------------------------------------------------------------------ void ErrlManager::setupPnorInfo() { TRACFCOMP( g_trac_errl, ENTER_MRK"setupPnorInfo" ); do { // Get SPD PNOR section info from PNOR RP PNOR::SectionInfo_t info; errlHndl_t err = PNOR::getSectionInfo( PNOR::HB_ERRLOGS, info ); if (err) { TRACFCOMP( g_trac_errl, INFO_MRK"setupPnorInfo getSectionInfo failed"); assert(err == NULL); break; } TRACFCOMP( g_trac_errl, INFO_MRK"setupPnorInfo sectionInfo id %d name \"%s\" size %d", info.id, info.name, info.size ); // Set the globals appropriately iv_pnorAddr = reinterpret_cast<char *> (info.vaddr); iv_maxErrlInPnor = info.size / PNOR_ERROR_LENGTH; TRACFCOMP( g_trac_errl, INFO_MRK"setupPnorInfo iv_pnorAddr %p maxErrlInPnor %d", iv_pnorAddr, iv_maxErrlInPnor ); // initial value, in case PNOR is empty - start at this end slot // so that our first save will increment and wrap correctly iv_pnorOpenSlot = (iv_maxErrlInPnor - 1); // walk thru memory, finding error logs and determine the highest ID uint32_t l_maxId = 0; for (uint32_t i = 0; i < iv_maxErrlInPnor; i++) { if (!isSlotEmpty(i)) { uint32_t l_id = readEidFromFlattened(i); // If id is not from HB (0x9XXXXXXX) grab plid instead if ( (l_id & FIRST_BYTE_ERRLOG) != ERRLOG_PLID_BASE ) { l_id = readPlidFromFlattened(i); } if (l_id > l_maxId ) { l_maxId = l_id; // set this - start at this 'max' slot so that our first // save will increment correctly iv_pnorOpenSlot = i; } // also check if it's ACKed or not. and ACK it. // for FSP system, this shouldn't ever happen. // for non-FSP systems, this clears out all 'last IPL' logs if (!isSlotACKed(i)) { TRACFCOMP( g_trac_errl, INFO_MRK"setupPnorInfo slot %d eid %.8X was not ACKed.", i, l_id); setACKInFlattened(i); } // not ACKed } // not empty } // for // bump the current eid to 1 past the max eid found while (!__sync_bool_compare_and_swap(&iv_currLogId, iv_currLogId, (iv_currLogId & ERRLOG_PLID_BASE_MASK) + (l_maxId & ERRLOG_PLID_MASK) + 1)); TRACFCOMP( g_trac_errl, INFO_MRK"setupPnorInfo reseting LogId 0x%X", iv_currLogId); // if error(s) came in before PNOR was ready, // the error log(s) would be on this list. save now. ErrlListItr_t it = iv_errlList.begin(); while(it != iv_errlList.end()) { // Check if PNOR processing is needed if (_isPnorFlagSet(*it)) { //ACK it if no one is there to receive bool l_savedToPnor = saveErrLogToPnor(it->first); // check if we actually saved the msg to PNOR if (l_savedToPnor) { // Mark PNOR processing complete _clearPnorFlag(*it); _updateErrlListIter(it); } else { // still couldn't save it (PNOR maybe full) so // it's still on the list. break; // get out of this while loop. } } else { ++it; } } } while (0); TRACFCOMP( g_trac_errl, EXIT_MRK"setupPnorInfo"); } // setupPnorInfo