diff options
author | Brian Horton <brianh@linux.ibm.com> | 2014-10-16 11:40:21 -0500 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2015-01-22 16:59:09 -0600 |
commit | 1bc13e89d35eacba76589ac3c5158d54ce73b35b (patch) | |
tree | 749478e2e2fb8c250c682d49dae2c9a524d4f8cb /src | |
parent | abf9c4a78fcac4e2951e504523ea04cecda59b63 (diff) | |
download | talos-hostboot-1bc13e89d35eacba76589ac3c5158d54ce73b35b.tar.gz talos-hostboot-1bc13e89d35eacba76589ac3c5158d54ce73b35b.zip |
add SEL/eSEL support
in errlmanager, convert errlog to SEL/eSEL format,
prepare to send to BMC via IPMI
Change-Id: I11e246264840ff756e92b97673e4742b9d03daad
RTC: 114908
Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/14238
Tested-by: Jenkins Server
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/include/usr/errl/errlipmi.H | 142 | ||||
-rw-r--r-- | src/include/usr/errl/errlmanager.H | 111 | ||||
-rw-r--r-- | src/include/usr/errl/errlprvt.H | 5 | ||||
-rw-r--r-- | src/usr/errl/errlmanager.C | 237 | ||||
-rw-r--r-- | src/usr/ipmi/ipmirp.C | 3 |
5 files changed, 391 insertions, 107 deletions
diff --git a/src/include/usr/errl/errlipmi.H b/src/include/usr/errl/errlipmi.H new file mode 100644 index 000000000..836b0d1a1 --- /dev/null +++ b/src/include/usr/errl/errlipmi.H @@ -0,0 +1,142 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/include/usr/errl/errlipmi.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* [+] 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 */ +#ifndef ERRLIPMI_H +#define ERRLIPMI_H +/** + * @file errlipmi.H + * + * @brief Error Log for IPMI SEL/eSEL formats + * + * This header file contains the definition of error structures for ipmi + * + */ + +/*****************************************************************************/ +// I n c l u d e s +/*****************************************************************************/ +#include <stdint.h> + +namespace ERRORLOG +{ + +// per MegaRAC SP-X spec +// The size of the eSEL is configurable via PRJ +// it can be set to 2KB per eSEL packet. +static const uint32_t ESEL_MAX_SIZE = 2 * KILOBYTE; + +// per MegaRAC SP-X spec +static const uint8_t SEL_RECORD_TYPE = 0xDE; +static const uint8_t ESEL_RECORD_TYPE = 0xDF; + +// per MegaRAC SP-X spec +static const uint8_t ESEL_EVENT_DATA_1 = 0xAA; + + +// per MegaRAC SP-X spec +static const uint16_t SEL_GENERATOR_ID = 0x2000; + +// per MegaRAC SP-X spec +static const uint8_t SEL_FORMAT_VERSION = 0x04; + + +// per IPMI Spec, section 32.1 SEL Event Records +struct selRecord +{ + + // ID used for SEL Record access. The Record ID values 0000h and FFFFh + // have special meaning in the Event Access commands and must not be + // used as Record ID values for stored SEL Event Records. + uint16_t recordID; + + // [7:0] - Record Type + // 02h = system event record + // C0h-DFh = OEM timestamped, bytes 8-16 OEM defined + // E0h-FFh = OEM non-timestamped, bytes 4-16 OEM defined + uint8_t record_type; + + // Time when event was logged. LS byte first. + uint32_t timestamp; + + // RqSA & LUN if event was generated from IPMB. Software ID if event was + // generated from system software. + // Byte 1 + // [7:1] - 7-bit I2C. Slave Address, or 7-bit system software ID + // [0] 0b = ID is IPMB Slave Address + // 1b = system software ID + // Byte 2 + // [7:4] - Channel number. Channel that event message was received over. + // 0h if the event message was received via the system interface, + // primary IPMB, or internally generated by the BMC. + // [3:2] - reserved. Write as 00b. + // [1:0] - IPMB device LUN if byte 1 holds Slave Address. 00b otherwise. + uint16_t generator_id; + + // Event Message format version + // (=04h for events in this specification, + // 03h for IPMI v1.0 Event Messages.) + uint8_t evm_format_version; + + // Sensor Type Code for sensor that generated the event + uint8_t sensor_type; + + // Number of sensor that generated the event + uint8_t sensor_number; + + // Event Dir + // [7 ] 0b = Assertion event. + // 1b = Deassertion event. + // Event Type + // Type of trigger for the event, e.g. critical threshold going high, + // state asserted, etc. Also indicates class of the event. E.g. + // discrete, threshold, or OEM. The Event Type field is encoded + // using the Event/Reading Type Code. + // [6:0] - Event Type Code + + uint8_t event_dir_type; + + uint8_t event_data1; + uint8_t event_data2; + uint8_t event_data3; + + // ctor + selRecord(): + recordID(0), + record_type(0), + timestamp(0), + generator_id(SEL_GENERATOR_ID), + evm_format_version(SEL_FORMAT_VERSION), + sensor_type(0), + sensor_number(0), + event_dir_type(0), + event_data1(0), + event_data2(0), + event_data3(0) + { }; + +} PACKED; + +} // End namespace + +#endif //ERRLIPMI_H diff --git a/src/include/usr/errl/errlmanager.H b/src/include/usr/errl/errlmanager.H index 38291e546..07d4b79af 100644 --- a/src/include/usr/errl/errlmanager.H +++ b/src/include/usr/errl/errlmanager.H @@ -39,6 +39,7 @@ #include <util/singleton.H> #include <errl/errlentry.H> #include <errldisplay/errldisplay.H> +#include <errl/errlipmi.H> #include <sys/sync.h> #include <kernel/timemgr.H> #include <hbotcompid.H> @@ -80,6 +81,7 @@ enum errlManagerNeeds PNOR, TARG, MBOX, + IPMI, ERRLDISP, } ; @@ -146,7 +148,7 @@ public: * @brief Sends msg to errlmanager telling what resources are ready * * This is called by resources that the ErrlManager needs, which start up - * AFTER ErrlManager starts. Currently, that's PNOR MBOX and TARGeting. + * AFTER ErrlManager starts. * * It is a static function because a module cannot call an interface on a * singleton in another module @@ -221,6 +223,7 @@ private: ERRLOG_ACCESS_MBOX_TYPE = 0x00000035 | MBOX::FIRST_SECURE_MSG, ERRLOG_ACCESS_TARG_TYPE = 0x00000036 | MBOX::FIRST_SECURE_MSG, ERRLOG_ACCESS_ERRLDISP_TYPE = 0x00000037 | MBOX::FIRST_SECURE_MSG, + ERRLOG_ACCESS_IPMI_TYPE = 0x00000038 | MBOX::FIRST_SECURE_MSG, }; /** @@ -300,7 +303,7 @@ private: * @param[in,out] io_err Error log handle to be committed * */ - void sendErrLogToMbox ( errlHndl_t& io_err ); + void sendErrLogToFSP ( errlHndl_t& io_err ); /** * @brief Create a mailbox message with the error log and send it to Fsp. @@ -435,16 +438,27 @@ private: */ void setACKInFlattened(uint32_t i_position); +#ifdef CONFIG_BMC_IPMI + /** + * @brief Create an ipmi message with the error log and send it to BMC + * + * @param[in,out] io_err Error log handle to be committed + * + */ + void sendErrLogToBmc(errlHndl_t &io_err); +#endif + /** * @brief errorlog-into-PNOR variables */ char *iv_pnorAddr; // HBEL section in PNOR uint32_t iv_maxErrlInPnor; // max number of errorlogs that will fit uint32_t iv_pnorOpenSlot; // current open slot available for an errorlog - bool iv_isSpBaseServices; // do we need to send to FSP - bool iv_isMboxEnabled; // are we able to send to FSP - bool iv_nonInfoCommitted; //< Keeps track of any non-informational logs. - bool iv_isErrlDisplayEnabled; // are we able to use the errorDisplay + bool iv_isSpBaseServices; // do we need to send to FSP + bool iv_isMboxEnabled; // are we able to send to FSP + bool iv_isIpmiEnabled; // are we able to send to BMC via IPMI + bool iv_nonInfoCommitted; // Keeps track of any non-informational logs. + bool iv_isErrlDisplayEnabled; // are we able to use the errorDisplay // Errl flags which represent processing needed by the errl // represented as a bit field (8 bits) @@ -454,89 +468,49 @@ private: PNOR_FLAG = 0x01, MBOX_FLAG = 0x02, ERRLDISP_FLAG = 0x04, + IPMI_FLAG = 0x08, + ALL_FLAGS = PNOR_FLAG | MBOX_FLAG + #ifdef CONFIG_BMC_IPMI + | IPMI_FLAG + #endif #ifdef CONFIG_CONSOLE_OUTPUT_ERRORDISPLAY - ALL_FLAGS = PNOR_FLAG | MBOX_FLAG | ERRLDISP_FLAG, - #else - ALL_FLAGS = PNOR_FLAG | MBOX_FLAG, + | ERRLDISP_FLAG #endif }; // List of messages errl manager needs to handle // The unint8_t is a bit field to indiciate what needs to be done - std::list<std::pair<errlHndl_t, uint8_t> > iv_errlList; - - typedef std::list<std::pair<errlHndl_t, uint8_t> >::iterator ErrlListItr_t; - - /** - * @brief checks if the pnor flag is set - * - * @param[in] i_pair - pair of errl and bitfield of flags - * @return True if PNOR flag is set - * - */ - static bool _isPnorFlagSet(const std::pair<errlHndl_t, uint8_t> &i_pair) - { - return (i_pair.second & PNOR_FLAG); - } - - /** - * @brief checks if the mbox flag is set - * - * @param[in] i_pair - pair of errl and bitfield of flagst - * @return True if mbox flag is set - * - */ - static bool _isMboxFlagSet(const std::pair<errlHndl_t, uint8_t> &i_pair) - { - return (i_pair.second & MBOX_FLAG); - } + typedef std::pair<errlHndl_t, uint8_t> ErrlFlagPair_t; + typedef std::list<ErrlFlagPair_t> ErrlList_t; + typedef ErrlList_t::iterator ErrlListItr_t; + ErrlList_t iv_errlList; /** - * @brief checks if the errldisp flag is set + * @brief checks if the flag is set * * @param[in] i_pair - pair of errl and bitfield of flags - * @return True if errldisp flag is set - * - */ - static bool _isErrlDispFlagSet(const std::pair<errlHndl_t, uint8_t> &i_pair) - { - return (i_pair.second & ERRLDISP_FLAG); - } - - /** - * @brief clears the pnor flag, indicating complete - * - * @param[in/out] io_pair - pair of errl and bitfield of flags - * @return NA - * - */ - static void _clearPnorFlag(std::pair<errlHndl_t, uint8_t> &io_pair) - { - io_pair.second &= ~PNOR_FLAG; - } - - /** - * @brief clears the mbox flag, indicating complete - * - * @param[in/out] io_pair - pair of errl and bitfield of flags - * @return NA + * @param[in] i_flag - specific flag + * @return True if specified flag is set * */ - static void _clearMboxFlag(std::pair<errlHndl_t, uint8_t> &io_pair) + static bool _isFlagSet(const ErrlFlagPair_t &i_pair, + const ERRLOG_FLAGS i_flag) { - io_pair.second &= ~MBOX_FLAG; + return (i_pair.second & i_flag); } /** - * @brief clears the errldisp flag, indicating complete + * @brief clears the flag, indicating complete * * @param[in/out] io_pair - pair of errl and bitfield of flags + * @param[in] i_flag - specific flag * @return NA * */ - static void _clearErrlDispFlag(std::pair<errlHndl_t, uint8_t> &io_pair) + static void _clearFlag(ErrlFlagPair_t &io_pair, + const ERRLOG_FLAGS i_flag) { - io_pair.second &= ~ERRLDISP_FLAG; + io_pair.second &= ~i_flag; } /** @@ -549,8 +523,7 @@ private: * @return True if an erase occurred, otherwise false * */ - bool _updateErrlListIter(std::list< std::pair<errlHndl_t, uint8_t> > - ::iterator & io_it); + bool _updateErrlListIter(ErrlListItr_t & io_it); }; diff --git a/src/include/usr/errl/errlprvt.H b/src/include/usr/errl/errlprvt.H index 5a779187c..b3cc68d91 100644 --- a/src/include/usr/errl/errlprvt.H +++ b/src/include/usr/errl/errlprvt.H @@ -5,7 +5,9 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* COPYRIGHT International Business Machines Corp. 2011,2014 */ +/* Contributors Listed Below - COPYRIGHT 2011,2015 */ +/* [+] 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. */ @@ -44,6 +46,7 @@ class ErrlPrvt // you would expect to be part of ErrlEntry are actually instance data // in this class. friend class ErrlEntry; + friend class ErrlManager; private: diff --git a/src/usr/errl/errlmanager.C b/src/usr/errl/errlmanager.C index 24209326c..5f9294381 100644 --- a/src/usr/errl/errlmanager.C +++ b/src/usr/errl/errlmanager.C @@ -51,6 +51,7 @@ #include <console/consoleif.H> #include <config.h> #include <functional> +#include <util/lockfree/counter.H> namespace ERRORLOG { @@ -120,7 +121,8 @@ ErrlManager::ErrlManager() : iv_maxErrlInPnor(0), iv_pnorOpenSlot(0), iv_isSpBaseServices(true), // queue msgs for fsp until we find we shouldn't - iv_isMboxEnabled(false), // but mbox isn't ready yet.. + iv_isMboxEnabled(false), // assume mbox isn't ready yet.. + iv_isIpmiEnabled(false), // assume ipmi isn't ready yet.. iv_nonInfoCommitted(false), iv_isErrlDisplayEnabled(false) { @@ -271,13 +273,14 @@ void ErrlManager::errlogMsgHndlr () { iv_isSpBaseServices = false; - // if there are queued msgs, delete the errors that - // have been fully processed + // if there are queued errors, clear the Mbox flag + // since they will never be sent, which will delete + // the errors that have been fully processed ErrlListItr_t it = iv_errlList.begin(); while(it != iv_errlList.end()) { // Mark MBOX processing complete - _clearMboxFlag(*it); + _clearFlag(*it, MBOX_FLAG); _updateErrlListIter(it); } } @@ -324,17 +327,18 @@ void ErrlManager::errlogMsgHndlr () assert(0); } - // if error(s) came in before MBOX was ready, - // the msg(s) would be on this list. send it now. + // if errors came in before MBOX was ready, + // the errors would be on this list. send them now. ErrlListItr_t it = iv_errlList.begin(); while(it != iv_errlList.end()) { // Check if MBOX processing is needed - if (_isMboxFlagSet(*it)) + if (_isFlagSet(*it, MBOX_FLAG)) { + // send errlog + sendErrLogToFSP(it->first); // Mark MBOX processing complete - sendErrLogToMbox(it->first); - _clearMboxFlag(*it); + _clearFlag(*it, MBOX_FLAG); } _updateErrlListIter(it); } @@ -346,7 +350,7 @@ void ErrlManager::errlogMsgHndlr () while(it != iv_errlList.end()) { // Mark MBOX processing complete - _clearMboxFlag(*it); + _clearFlag(*it, MBOX_FLAG); _updateErrlListIter(it); } } @@ -357,6 +361,36 @@ void ErrlManager::errlogMsgHndlr () // go back and wait for a next msg break; } + case ERRLOG_ACCESS_IPMI_TYPE: + { +#ifdef CONFIG_BMC_IPMI + // IPMI is up and running now. + iv_isIpmiEnabled = true; + + // if we can now send msgs, do it. + // if errors came in before IPMI was ready, + // the errors would be on this list. send them now. + ErrlListItr_t it = iv_errlList.begin(); + while(it != iv_errlList.end()) + { + // Check if IPMI processing is needed + if (_isFlagSet(*it, IPMI_FLAG)) + { + // send errorlog + sendErrLogToBmc(it->first); + // Mark IPMI processing complete + _clearFlag(*it, IPMI_FLAG); + } + _updateErrlListIter(it); + } +#endif + + //We are done with the msg + msg_free(theMsg); + + // go back and wait for a next msg + break; + } case ERRLOG_ACCESS_ERRLDISP_TYPE: { #ifdef CONFIG_CONSOLE_OUTPUT_ERRORDISPLAY @@ -371,13 +405,13 @@ void ErrlManager::errlogMsgHndlr () while(it != iv_errlList.end()) { // Check if ERRLDISP processing is needed - if (_isErrlDispFlagSet(*it)) + if (_isFlagSet(*it, ERRLDISP_FLAG)) { ERRORLOGDISPLAY::errLogDisplay().msgDisplay (it->first, ((it->first->reasonCode()) & 0xFF00)); // Mark ERRLDISP processing complete - _clearErrlDispFlag(*it); + _clearFlag(*it, ERRLDISP_FLAG); } _updateErrlListIter(it); } @@ -390,25 +424,24 @@ void ErrlManager::errlogMsgHndlr () case ERRLOG_NEEDS_TO_BE_COMMITTED_TYPE: { // Extract error log handle from the message. We need the - // error log handle to pass along to saveErrLogEntry and - // sendErrLogToMbox + // error log handle to pass along errlHndl_t l_err = (errlHndl_t) theMsg->extra_data; - //Ask the ErrlEntry to assign commit component, commit time + // Ask the ErrlEntry to assign commit component, commit time l_err->commit( (compId_t) theMsg->data[0] ); // Pair with all flags set to add to the errlList - std::pair<errlHndl_t, uint8_t> l_pair(l_err, ALL_FLAGS); + ErrlFlagPair_t l_pair(l_err, ALL_FLAGS); - // Display errl to errldisplay #ifdef CONFIG_CONSOLE_OUTPUT_ERRORDISPLAY + // Display errl to errldisplay if (iv_isErrlDisplayEnabled) { ERRORLOGDISPLAY::errLogDisplay().msgDisplay (l_err, ( (l_err->reasonCode()) & 0xFF00)); // Mark ERRLDISP processing complete on this error - _clearErrlDispFlag(l_pair); + _clearFlag(l_pair, ERRLDISP_FLAG); } #endif //Save the error log to PNOR @@ -418,7 +451,7 @@ void ErrlManager::errlogMsgHndlr () if (l_savedToPnor) { // Mark PNOR processing complete on this error - _clearPnorFlag(l_pair); + _clearFlag(l_pair, PNOR_FLAG); } #ifdef STORE_ERRL_IN_L3 @@ -427,19 +460,31 @@ void ErrlManager::errlogMsgHndlr () saveErrLogEntry ( l_err ); #endif - // Try to send the error log if someone is there to receive + //Try to send the error log if someone is there to receive if (!iv_isSpBaseServices) { // Mark MBOX processing complete on this error - _clearMboxFlag(l_pair); + _clearFlag(l_pair, MBOX_FLAG); } else if (iv_isSpBaseServices && iv_isMboxEnabled) { - sendErrLogToMbox(l_err); + sendErrLogToFSP(l_err); + // Mark MBOX processing complete on this error - _clearMboxFlag(l_pair); + _clearFlag(l_pair, MBOX_FLAG); } +#ifdef CONFIG_BMC_IPMI + if (iv_isIpmiEnabled) + { + // convert to SEL/eSEL and send to BMC over IPMI + sendErrLogToBmc(l_err); + + // Mark IPMI processing complete on this error + _clearFlag(l_pair, IPMI_FLAG); + } +#endif + //Ask the ErrlEntry to process any callouts l_err->processCallout(); @@ -495,7 +540,7 @@ void ErrlManager::errlogMsgHndlr () { // We found the errlog // Mark PNOR processing complete - _clearPnorFlag(*it); + _clearFlag(*it, PNOR_FLAG); _updateErrlListIter(it); } } @@ -505,8 +550,9 @@ void ErrlManager::errlogMsgHndlr () // We didn't have room before in PNOR to save an // error log, so try now since we just ACKed one. ErrlListItr_t it = std::find_if(iv_errlList.begin(), - iv_errlList.end(), - _isPnorFlagSet); + iv_errlList.end(), + bind2nd(ptr_fun(_isFlagSet), + PNOR_FLAG)); // Check if such errl was found if (it != iv_errlList.end()) @@ -517,7 +563,7 @@ void ErrlManager::errlogMsgHndlr () if (l_savedToPnor) { // Mark PNOR processing complete - _clearPnorFlag(*it); + _clearFlag(*it, PNOR_FLAG); _updateErrlListIter(it); } // else, still couldn't save it (for some reason) so @@ -556,13 +602,13 @@ void ErrlManager::errlogMsgHndlr () /////////////////////////////////////////////////////////////////////////////// -// ErrlManager::sendErrLogToMbox() +// ErrlManager::sendErrLogToFSP() /////////////////////////////////////////////////////////////////////////////// -void ErrlManager::sendErrLogToMbox ( errlHndl_t& io_err ) +void ErrlManager::sendErrLogToFSP ( errlHndl_t& io_err ) { msg_t *msg = NULL; - TRACFCOMP( g_trac_errl, ENTER_MRK"ErrlManager::sendErrLogToMbox" ); + TRACFCOMP( g_trac_errl, ENTER_MRK"ErrlManager::sendErrLogToFSP" ); do { //Create a mailbox message to send to FSP @@ -605,8 +651,8 @@ void ErrlManager::sendErrLogToMbox ( errlHndl_t& io_err ) } } while (0); - TRACFCOMP( g_trac_errl, EXIT_MRK"ErrlManager::sendErrLogToMbox" ); -} // sendErrLogToMbox + TRACFCOMP( g_trac_errl, EXIT_MRK"ErrlManager::sendErrLogToFSP" ); +} // sendErrLogToFSP /////////////////////////////////////////////////////////////////////////////// // Handling commit error log. @@ -750,6 +796,9 @@ void ErrlManager::sendResourcesMsg(errlManagerNeeds i_needs) case MBOX: msg->type = ERRORLOG::ErrlManager::ERRLOG_ACCESS_MBOX_TYPE; break; + case IPMI: + msg->type = ERRORLOG::ErrlManager::ERRLOG_ACCESS_IPMI_TYPE; + break; case ERRLDISP: msg->type = ERRORLOG::ErrlManager::ERRLOG_ACCESS_ERRLDISP_TYPE; break; @@ -822,7 +871,7 @@ void ErrlManager::sendErrlogToMessageQueue ( errlHndl_t& io_err, } while (0); TRACFCOMP( g_trac_errl, EXIT_MRK"ErrlManager::sendErrlogToMessageQueue" ); return; -} +} // sendErrlogToMessageQueue /////////////////////////////////////////////////////////////////////////////// // ErrlManager::errlogShutdown() @@ -834,11 +883,11 @@ void ErrlManager::errlogShutdown() while (!iv_errlList.empty()) { // Get errl and its flags - std::pair<errlHndl_t, uint8_t> l_pair = iv_errlList.front(); + ErrlFlagPair_t l_pair = iv_errlList.front(); // If still true that means it was not processed TRACFCOMP(g_trac_errl, INFO_MRK "Failed to fully process Errl(eid %.8x) - Errl Flags Bitfield = 0x%X", - l_pair.second); + l_pair.first->eid(), l_pair.second); delete l_pair.first; l_pair.first = NULL; @@ -991,7 +1040,7 @@ void ErrlManager::setupPnorInfo() while(it != iv_errlList.end()) { // Check if PNOR processing is needed - if (_isPnorFlagSet(*it)) + if (_isFlagSet(*it, PNOR_FLAG)) { //ACK it if no one is there to receive bool l_savedToPnor = saveErrLogToPnor(it->first); @@ -1000,7 +1049,7 @@ void ErrlManager::setupPnorInfo() if (l_savedToPnor) { // Mark PNOR processing complete - _clearPnorFlag(*it); + _clearFlag(*it, PNOR_FLAG); _updateErrlListIter(it); } else @@ -1234,4 +1283,118 @@ bool ErrlManager::_updateErrlListIter(ErrlListItr_t & io_it) return l_removed; } +#ifdef CONFIG_BMC_IPMI +void ErrlManager::sendErrLogToBmc(errlHndl_t &io_err) +{ + TRACFCOMP(g_trac_errl, ENTER_MRK + "sendErrLogToBmc errlogId 0x%.8x", io_err->eid()); + + do { + + // if it's an INFORMATIONAL log, we don't want to waste the cycles + if (io_err->sev() == ERRORLOG::ERRL_SEV_INFORMATIONAL) + { + TRACFCOMP( g_trac_errl, INFO_MRK + "sendErrLogToBmc: INFORMATIONAL log, skipping"); + break; + } + + // TODO: RTC 117526 + // look through the error log and determine what callouts there are, + // and what the corresponding sensors are. if there aren't any, then + // break; + + // flatten into bufffer, truncate to 2K + uint32_t l_plidSize = io_err->flattenedSize(); + if (l_plidSize > (ESEL_MAX_SIZE - sizeof(selRecord))) + { + TRACFCOMP( g_trac_errl, INFO_MRK + "sendErrLogToBmc: msg size %d > 2K, truncating.", + l_plidSize); + l_plidSize = ESEL_MAX_SIZE - sizeof(selRecord); + } + + uint8_t *l_plidData = new uint8_t[l_plidSize]; + uint32_t l_errSize = io_err->flatten (l_plidData, + l_plidSize, true /* truncate */); + + if (l_errSize ==0) + { + // flatten didn't work + TRACFCOMP( g_trac_errl, ERR_MRK + "sendErrLogToBmc: could not flatten data - not sending"); + delete [] l_plidData; + break; + } + + static uint16_t cv_recordID = 0; + + // 0x0000 and 0xffff are reserved; handle wrap + uint16_t l_nextRecordID = cv_recordID++; + if (l_nextRecordID == 0xffff) + { + // force a wrap + TRACFCOMP( g_trac_errl, ERR_MRK + "sendErrLogToBmc: wrapping on recordID!"); + cv_recordID = 1; + l_nextRecordID = cv_recordID; + } + selRecord *l_sel = new selRecord(); + l_sel->recordID = l_nextRecordID; + uint16_t eSelRecordID = cv_recordID++; + + l_sel->record_type = SEL_RECORD_TYPE; // per AMI spec - SEL + l_sel->timestamp = io_err->iv_Private.iv_committed; + l_sel->generator_id = SEL_GENERATOR_ID; + l_sel->evm_format_version = SEL_FORMAT_VERSION; + // TODO: RTC 117526 - sensor data + l_sel->sensor_type = 1; + l_sel->sensor_number = 1; + l_sel->event_dir_type = 1; + l_sel->event_data1 = ESEL_EVENT_DATA_1; // per AMI spec + l_sel->event_data2 = ((eSelRecordID & 0xFF00) >> 8); + l_sel->event_data3 = (eSelRecordID & 0x00FF); + + + // first part is a selRecord + selRecord *l_esel = new selRecord(); + l_esel->recordID = eSelRecordID; + l_esel->record_type = ESEL_RECORD_TYPE; // per AMI spec - eSEL + l_esel->timestamp = io_err->iv_Private.iv_committed; + l_esel->generator_id = SEL_GENERATOR_ID; + l_esel->evm_format_version = SEL_FORMAT_VERSION; + l_esel->sensor_type = 1; // per AMI spec + l_esel->sensor_number = 1; // per AMI spec + l_esel->event_dir_type = 1; // per AMI spec + l_esel->event_data1 = ESEL_EVENT_DATA_1; // per AMI spec + l_esel->event_data2 = 0; // per AMI spec + l_esel->event_data3 = 0; // per AMI spec + + // send it to the BMC over IPMI + TRACFCOMP(g_trac_errl, INFO_MRK "sendErrLogToBmc: sent SEL %d, eSEL %d", + l_sel->recordID, l_esel->recordID); + + // TODO: RTC 117454 call IPMI send_sel i/f when it's ready +#if 0 + errlHndl_t l_err = sendSel(&l_sel, &l_esel, &l_plidData, l_plidSize); + if (l_err) + { + TRACFCOMP(g_trac_errl, ERR_MRK "sendSel(%d,%d,%d) returned error", + l_sel->recordID, l_esel->recordID, l_plidSize); + errlCommit(l_err, IPMI_COMP_ID); + } +#else + // free the buffers + delete l_sel; + delete l_esel; + delete [] l_plidData; +#endif + + + } while(0); + + TRACFCOMP(g_trac_errl, EXIT_MRK "sendErrLogToBmc"); +} // sendErrLogToBmc +#endif + } // End namespace diff --git a/src/usr/ipmi/ipmirp.C b/src/usr/ipmi/ipmirp.C index fba8262d1..9112fdabd 100644 --- a/src/usr/ipmi/ipmirp.C +++ b/src/usr/ipmi/ipmirp.C @@ -462,6 +462,9 @@ void IpmiRP::execute(void) // Wait for an event message read it and handle it if no one else does task_create( &IpmiRP::last_chance_event_handler, NULL); + // call ErrlManager function - tell him that IPMI is ready! + ERRORLOG::ErrlManager::errlResourceReady(ERRORLOG::IPMI); + while (true) { msg_t* msg = msg_wait(iv_msgQ); |