diff options
author | Brian Horton <brianh@linux.ibm.com> | 2015-01-31 22:04:46 -0600 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2015-02-16 14:52:32 -0600 |
commit | 7ff96947e3424a8d8909f7de37c1442b6e8d7a18 (patch) | |
tree | 80092d07d0af9f6b14f5a3c9fb2203902880dfe6 /src | |
parent | 8fcc72d4f487e90f5d9c5bc333a50a5d25703da6 (diff) | |
download | talos-hostboot-7ff96947e3424a8d8909f7de37c1442b6e8d7a18.tar.gz talos-hostboot-7ff96947e3424a8d8909f7de37c1442b6e8d7a18.zip |
error log to esel integration
Change-Id: I2f134d73b114e4177e3e285defd85fbc21153913
RTC: 117454
Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/15466
Tested-by: Jenkins Server
Reviewed-by: STEPHEN M. CPREK <smcprek@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
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 | 25 | ||||
-rw-r--r-- | src/include/usr/errl/errlsctn.H | 3 | ||||
-rw-r--r-- | src/include/usr/errl/errlsctnhdr.H | 3 | ||||
-rw-r--r-- | src/include/usr/errl/errlud.H | 3 | ||||
-rw-r--r-- | src/include/usr/hwas/common/hwasCallout.H | 29 | ||||
-rw-r--r-- | src/include/usr/ipmi/ipmiif.H | 5 | ||||
-rw-r--r-- | src/include/usr/ipmi/ipmisel.H | 264 | ||||
-rw-r--r-- | src/usr/errl/errlmanager.C | 185 | ||||
-rw-r--r-- | src/usr/hwas/hostbootIstep.C | 6 | ||||
-rw-r--r-- | src/usr/ipmi/ipmisel.C | 345 | ||||
-rw-r--r-- | src/usr/ipmi/ipmisel.H | 115 |
12 files changed, 629 insertions, 496 deletions
diff --git a/src/include/usr/errl/errlipmi.H b/src/include/usr/errl/errlipmi.H deleted file mode 100644 index 836b0d1a1..000000000 --- a/src/include/usr/errl/errlipmi.H +++ /dev/null @@ -1,142 +0,0 @@ -/* 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 07d4b79af..a5fcc136b 100644 --- a/src/include/usr/errl/errlmanager.H +++ b/src/include/usr/errl/errlmanager.H @@ -39,7 +39,6 @@ #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> @@ -156,13 +155,15 @@ public: static void errlResourceReady(errlManagerNeeds i_needs); /** - * @brief Sends msg to errlmanager telling what resources are ready + * @brief Sends msg to errlmanager to ack sending of errl to BMC * - * This is called by resources that the ErrlManager needs, which start up - * AFTER ErrlManager starts. Currently, that's PNOR MBOX and TARGeting. + * This is called by ipmi code once the SEL for the indicated errorlog + * has been successfully sent to the BMC * + * It is a static function because a module cannot call an interface on a + * singleton in another module */ - void sendResourcesMsg(errlManagerNeeds i_needs); + static void errlAckErrorlog(uint32_t i_eid); /** * @brief Returns the HWAS ProcessCallout function pointer @@ -250,6 +251,20 @@ private: ErrlManager(const ErrlManager& i_right); ErrlManager& operator=(const ErrlManager& i_right); + /** + * @brief Sends msg to errlmanager telling what resources are ready + * + * called by static errlResourceReady function. + */ + void sendResourcesMsg(errlManagerNeeds i_needs); + + /** + * @brief Sends msg to errlmanager telling which errlog to ack + * + * called by static errlAckErrorlog function. + */ + void sendAckErrorlog(uint32_t i_eid); + /** * @brief Access PNOR and get the address and size of the HBEL section in * PNOR; sets the iv_pnorAddr, iv_maxErrlInPnor, iv_pnorOpenSlot variables; diff --git a/src/include/usr/errl/errlsctn.H b/src/include/usr/errl/errlsctn.H index 295786614..367e5de89 100644 --- a/src/include/usr/errl/errlsctn.H +++ b/src/include/usr/errl/errlsctn.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2014 */ +/* Contributors Listed Below - COPYRIGHT 2011,2015 */ /* [+] Google Inc. */ /* [+] International Business Machines Corp. */ /* */ @@ -59,6 +59,7 @@ namespace ERRORLOG */ class ErrlSctn { + friend class ErrlManager; friend class ERRORLOGDISPLAY::ErrLogDisplay; diff --git a/src/include/usr/errl/errlsctnhdr.H b/src/include/usr/errl/errlsctnhdr.H index 6d72018d1..bed8d3fcd 100644 --- a/src/include/usr/errl/errlsctnhdr.H +++ b/src/include/usr/errl/errlsctnhdr.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2014 */ +/* Contributors Listed Below - COPYRIGHT 2011,2015 */ /* [+] Google Inc. */ /* [+] International Business Machines Corp. */ /* */ @@ -69,6 +69,7 @@ class ErrlSctnHdr friend class ErrlUD; friend class ErrlSrc; friend class ErrlEntry; + friend class ErrlManager; friend class ERRORLOGDISPLAY::ErrLogDisplay; diff --git a/src/include/usr/errl/errlud.H b/src/include/usr/errl/errlud.H index d7c10cc0f..3e243049f 100644 --- a/src/include/usr/errl/errlud.H +++ b/src/include/usr/errl/errlud.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2014 */ +/* Contributors Listed Below - COPYRIGHT 2011,2015 */ /* [+] Google Inc. */ /* [+] International Business Machines Corp. */ /* */ @@ -54,6 +54,7 @@ class ErrlUD : public ErrlSctn // you would expect to be part of ErrlEntry are actually instance data // in this class. friend class ErrlEntry; + friend class ErrlManager; friend class ERRORLOGDISPLAY::ErrLogDisplay; diff --git a/src/include/usr/hwas/common/hwasCallout.H b/src/include/usr/hwas/common/hwasCallout.H index 3c6813dc7..f8611c0e8 100644 --- a/src/include/usr/hwas/common/hwasCallout.H +++ b/src/include/usr/hwas/common/hwasCallout.H @@ -93,6 +93,7 @@ enum epubProcedureID // from srci/fsp/srci.H enum callOutPriority { + SRCI_PRIORITY_NONE = 0, SRCI_PRIORITY_LOW = 1, SRCI_PRIORITY_MEDC = 2, SRCI_PRIORITY_MEDB = 3, @@ -161,23 +162,37 @@ typedef struct callout_ud // two Targets will follow }; struct { // type == CLOCK_CALLOUT - clockTypeEnum clockType; // uint32_t - DeconfigEnum clkDeconfigState; // uint32_t - GARD_ErrorType clkGardErrorType; // uint32_t + clockTypeEnum clockType; // uint32_t + DeconfigEnum clkDeconfigState; // uint32_t + GARD_ErrorType clkGardErrorType; // uint32_t // one Target will follow }; struct { // type == PART_CALLOUT - partTypeEnum partType; // uint32_t + partTypeEnum partType; // uint32_t DeconfigEnum partDeconfigState; // uint32_t GARD_ErrorType partGardErrorType; // uint32_t // one Target will follow }; - }; + }; // union } callout_ud_t; #ifndef PARSER /** + * @brief retrieveTarget will convert the EntityPath to a Target + * + * @param[in] io_uData pointer to the userdetail data + * @param[in] o_pTarget target that is found + * @param[in] io_errl Error log handle reference + * + * @return true if error and o_pTarget data not valid, + * false no error, o_pTarget data valid + */ +bool retrieveTarget(uint8_t * & io_uData, + TARGETING::Target * & o_pTarget, + errlHndl_t i_errl); + +/** * @brief processCallout process the userdetail for a callout, calling * the deconfigure and/or GARD funcationality as appropriate * @@ -295,11 +310,7 @@ errlHndl_t platHandlePartCallout( DeconfigEnum i_deconfigState = DECONFIG, GARD_ErrorType i_gardErrorType = GARD_Fatal); - #endif // not PARSER - - }; // end namespace - #endif diff --git a/src/include/usr/ipmi/ipmiif.H b/src/include/usr/ipmi/ipmiif.H index 29867f5eb..19d62c114 100644 --- a/src/include/usr/ipmi/ipmiif.H +++ b/src/include/usr/ipmi/ipmiif.H @@ -78,7 +78,8 @@ namespace IPMI NETFUN_STORAGE = (0x0a << 2), NETFUN_TRANPORT = (0x0c << 2), NETFUN_GRPEXT = (0x2c << 2), - NETFUN_IBM = (0x3a << 2), + NETFUN_AMI = (0x32 << 2), + NETFUN_IBM = (0x3a << 2), // Overload the OEM netfun for a "none" netfun. We use this as a // default for objects which will have their netfun filled in @@ -218,7 +219,7 @@ namespace IPMI //AMI-specific storage messages inline const command_t partial_add_esel(void) - { return std::make_pair(NETFUN_STORAGE, 0x32); } + { return std::make_pair(NETFUN_AMI, 0xf0); } // event messages inline const command_t platform_event(void) diff --git a/src/include/usr/ipmi/ipmisel.H b/src/include/usr/ipmi/ipmisel.H new file mode 100644 index 000000000..82d86bf6f --- /dev/null +++ b/src/include/usr/ipmi/ipmisel.H @@ -0,0 +1,264 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/ipmi/ipmisel.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 __IPMI_IPMISEL_H +#define __IPMI_IPMISEL_H + +/** + * @file ipmisel.H + * @brief IPMI system error log transport definition + */ + +#include <stdint.h> +#include <builtins.h> +#include <ipmi/ipmiif.H> + +/** + * + */ + +namespace IPMISEL +{ + enum msg_type + { + MSG_SEND_ESEL, + MSG_STATE_SHUTDOWN, + MSG_LAST_TYPE = MSG_STATE_SHUTDOWN, + }; + + enum sel_size_constants + { + // size of the partial_add_esel request (command) data + PARTIAL_ADD_ESEL_REQ = 7, + + // per MegaRAC SP-X spec + // The size of the eSEL is configurable via PRJ + // it can be set to 2KB per eSEL packet. + ESEL_MAX_SIZE = 2 * KILOBYTE, + }; + + /** + * @brief Send the eSEL data to the BMC + * @param[in] pointer to eSEL data + * @param[in] size of eSEL data + * @param[in] eid of errorlog for this eSEL (for ack) + * @param[in] event_dir_type for this eSEL + * @param[in] sensorType that caused the error/eSEL + * @param[in] sensorNumber that caused the error/eSEL + */ + void sendESEL(uint8_t* i_eselData, uint32_t i_dataSize, + uint32_t i_eid, uint8_t i_eventDirType, + uint8_t i_sensorType, uint8_t i_sensorNumber); + + // per IPMI Spec, section 32.1 SEL Event Records + enum sel_record_type + { + record_type_system_event = 0x02, + record_type_ami_esel = 0xDF, + }; + + enum sel_evm_format_version + { + format_ipmi_version_1_0 = 0x03, + format_ipmi_version_2_0 = 0x04, + }; + + enum sel_event_dir_type + { + event_unspecified = 0x00, + event_threshhold = 0x01, + event_state = 0x03, + event_predictive = 0x04, + event_limit = 0x05, + event_permformance = 0x06, + }; + + enum sel_event_data + { + event_data1_ami = 0xAA, + }; + + enum sel_generator_id + { + generator_id_ami = 0x2000, + }; + + 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(0), + evm_format_version(0), + sensor_type(0), + sensor_number(0), + event_dir_type(0), + event_data1(0), + event_data2(0), + event_data3(0) + { }; + + } PACKED; // selRecord + + // local structure needed to pass data between sendESEL command and the sel + // thread + struct eselInitData + { + size_t dataSize; + uint8_t eSel[sizeof(selRecord)]; + uint8_t *eSelExtra; + + // ctor + eselInitData(selRecord* i_eSEL, + uint8_t* i_extraData, uint32_t i_dataSize) + { + dataSize = i_dataSize; + memcpy(eSel,i_eSEL,sizeof(selRecord)); + eSelExtra = new uint8_t[i_dataSize]; + memcpy(eSelExtra, i_extraData, i_dataSize); + } + + // dtor + ~eselInitData() + { + delete eSelExtra; + } + }; +} // namespace IPMISEL + +class IpmiSEL +{ + public: + + /** + * Thread start routine for the resource provider + * @param[in] void*, unused + */ + static void* start(void* unused); + + /** + * Default constructor + */ + IpmiSEL(void); + + /** + * Destructor + */ + ~IpmiSEL(void); + + /** + * @brief Get the message queue associated with this FRU + * @param[in] void + * @return, a msg_q_t which is the message queue + */ + msg_q_t msgQueue(void) const + { return iv_msgQ; } + + private: + /** + * Entry point for the SEL transport definition + */ + void execute(void); + + /** + * @brief parse the msg and call send_esel to send the esel (handles if + * the SEL reservation is lost) + * @param[in] i_msg + */ + void process_esel(msg_t *i_msg) const; + + /** + * @brief do the actual ipmi calls to send the esel data to the bmc + * @param[in] i_data esel data + * @param[in] o_err any error generated during the send + * @param[in] o_cc ipmi completion code from last sendrecv + */ + void send_esel(IPMISEL::eselInitData * i_data, + errlHndl_t &o_err, IPMI::completion_code &o_cc) const; + + msg_q_t iv_msgQ; //!< ipmi message queue + + //Disallow copying of this class. + IpmiSEL& operator=(const IpmiSEL&); + IpmiSEL(const IpmiSEL&); +}; + +#endif diff --git a/src/usr/errl/errlmanager.C b/src/usr/errl/errlmanager.C index 5f9294381..2de94634b 100644 --- a/src/usr/errl/errlmanager.C +++ b/src/usr/errl/errlmanager.C @@ -35,6 +35,7 @@ // I n c l u d e s /*****************************************************************************/ #include <errl/errlmanager.H> +#include <errl/errlreasoncodes.H> #include <trace/interface.H> #include <errl/errlentry.H> #include <initservice/taskargs.H> @@ -49,9 +50,11 @@ #include <intr/interrupt.H> #include <errldisplay/errldisplay.H> #include <console/consoleif.H> +#include <hwas/common/hwasCallout.H> +#include <ipmi/ipmisel.H> +#include <ipmi/ipmisensor.H> #include <config.h> #include <functional> -#include <util/lockfree/counter.H> namespace ERRORLOG { @@ -821,6 +824,40 @@ void ErrlManager::sendResourcesMsg(errlManagerNeeds i_needs) return; } +/////////////////////////////////////////////////////////////////////////////// +// Global function (not a method on an object) to ack that the error log +// was sent to the BMC. +void ErrlManager::errlAckErrorlog(uint32_t i_eid) +{ + ERRORLOG::theErrlManager::instance().sendAckErrorlog(i_eid); + return; +} + +void ErrlManager::sendAckErrorlog(uint32_t i_eid) +{ + TRACFCOMP( g_trac_errl, ENTER_MRK"ErrlManager::sendAddErrorlog 0x%.8X", + i_eid); + + //Create a message to send to Host boot error message queue. + msg_t *msg = msg_allocate(); + msg->type = ERRLOG_COMMITTED_ACK_RESPONSE_TYPE; + //Pass along the eid of the error, shifted up to the first word + msg->data[0] = static_cast<uint64_t>(i_eid) << 32; + + //Send the msg asynchronously to error message queue to handle. + int rc = msg_send ( ERRORLOG::ErrlManager::iv_msgQ, msg ); + + //Return code is non-zero when the message queue is invalid + //or the message type is invalid. + if ( rc ) + { + TRACFCOMP( g_trac_errl, ERR_MRK "Failed (rc=%d) to send ack 0x%.8X message.", + rc, i_eid); + } + return; +} + + bool ErrlManager::errlCommittedThisBoot() { isync(); @@ -1295,101 +1332,93 @@ void ErrlManager::sendErrLogToBmc(errlHndl_t &io_err) if (io_err->sev() == ERRORLOG::ERRL_SEV_INFORMATIONAL) { TRACFCOMP( g_trac_errl, INFO_MRK - "sendErrLogToBmc: INFORMATIONAL log, skipping"); + "sendErrLogToBmc: %.8X is INFORMATIONAL; skipping", + io_err->eid()); 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; + // look thru the errlog for any Callout UserDetail sections + // to determine the sensor information for the SEL + uint8_t l_sensorNumber = SENSOR::INVALID_SENSOR; + uint8_t l_sensorType = SENSOR::INVALID_SENSOR; + HWAS::callOutPriority l_priority = HWAS::SRCI_PRIORITY_NONE; + for(std::vector<ErrlUD*>::const_iterator + it = io_err->iv_SectionVector.begin(); + it != io_err->iv_SectionVector.end(); + it++ ) + { + HWAS::callout_ud_t *l_ud = + reinterpret_cast<HWAS::callout_ud_t*>((*it)->iv_pData); + + // if this is a CALLOUT that will have a target + if ((ERRL_COMP_ID == (*it)->iv_header.iv_compId) && + (1 == (*it)->iv_header.iv_ver) && + (ERRL_UDT_CALLOUT == (*it)->iv_header.iv_sst) && + (HWAS::HW_CALLOUT == l_ud->type) + ) + { + // if this callout is higher than any previous + if (l_ud->priority > l_priority) + { + // get the sensor number for the target + uint8_t * l_uData = (uint8_t *)(l_ud + 1); + TARGETING::Target *l_target = NULL; + bool l_err = HWAS::retrieveTarget(l_uData, + l_target, io_err); + if (!l_err) + { + // got a target, now get the sensor number + l_sensorNumber = + SENSOR::getFaultSensorNumber(l_target); + + // and update the priority + l_priority = l_ud->priority; + } + } + } + } // for each SectionVector - // flatten into bufffer, truncate to 2K - uint32_t l_plidSize = io_err->flattenedSize(); - if (l_plidSize > (ESEL_MAX_SIZE - sizeof(selRecord))) +#if 0 +// TODO: RTC 119440 + if (l_sensorNumber != SENSOR::INVALID_SENSOR) + { + l_sensorType = SENSOR::getSensorType(l_sensorNumber); + } +#endif + + // flatten into buffer, truncate to max eSEL size + uint32_t l_pelSize = io_err->flattenedSize(); + if (l_pelSize > (IPMISEL::ESEL_MAX_SIZE - sizeof(IPMISEL::selRecord))) { TRACFCOMP( g_trac_errl, INFO_MRK - "sendErrLogToBmc: msg size %d > 2K, truncating.", - l_plidSize); - l_plidSize = ESEL_MAX_SIZE - sizeof(selRecord); + "sendErrLogToBmc: msg size %d > %d, truncating.", + l_pelSize, IPMISEL::ESEL_MAX_SIZE); + l_pelSize = IPMISEL::ESEL_MAX_SIZE - sizeof(IPMISEL::selRecord); } - uint8_t *l_plidData = new uint8_t[l_plidSize]; - uint32_t l_errSize = io_err->flatten (l_plidData, - l_plidSize, true /* truncate */); + uint8_t *l_pelData = new uint8_t[l_pelSize]; + uint32_t l_errSize = io_err->flatten (l_pelData, + l_pelSize, 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; + delete [] l_pelData; 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 - + TRACFCOMP(g_trac_errl, INFO_MRK + "sendErrLogToBmc: sensor %.2x/%.2x, size %d", + l_sensorType, l_sensorNumber, l_pelSize); + IPMISEL::sendESEL(l_pelData, l_pelSize, + io_err->eid(), IPMISEL::event_unspecified, + l_sensorType, l_sensorNumber); + + // free the buffer + delete [] l_pelData; } while(0); diff --git a/src/usr/hwas/hostbootIstep.C b/src/usr/hwas/hostbootIstep.C index 42e756a07..23e9d9f49 100644 --- a/src/usr/hwas/hostbootIstep.C +++ b/src/usr/hwas/hostbootIstep.C @@ -177,9 +177,11 @@ void* host_discover_targets( void *io_pArgs ) { uint8_t l_type = itr->first; uint64_t l_val = itr->second; - TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,"PRESENT> %s[%.2X]=%.8X%.8X", l_epath.pathElementTypeAsString(itr->first), l_type, l_val>>32, l_val&0xFFFFFFFF); + TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,"PRESENT> %s[%.2X]=%.8X%.8X", + l_epath.pathElementTypeAsString(itr->first), l_type, l_val>>32, l_val&0xFFFFFFFF); #if (!defined(CONFIG_CONSOLE_OUTPUT_TRACE) && defined(CONFIG_CONSOLE)) - CONSOLE::displayf( "PRESENT> %s[%.2X]=%.8X%.8X", l_epath.pathElementTypeAsString(itr->first), l_type, l_val>>32, l_val&0xFFFFFFFF ); + CONSOLE::displayf("HWAS", "PRESENT> %s[%.2X]=%.8X%.8X", + l_epath.pathElementTypeAsString(itr->first), l_type, l_val>>32, l_val&0xFFFFFFFF ); #endif } diff --git a/src/usr/ipmi/ipmisel.C b/src/usr/ipmi/ipmisel.C index c1159d52b..df746f011 100644 --- a/src/usr/ipmi/ipmisel.C +++ b/src/usr/ipmi/ipmisel.C @@ -27,7 +27,9 @@ * @brief IPMI system error log transport definition */ -#include "ipmisel.H" +#include <algorithm> +#include <sys/time.h> +#include <ipmi/ipmisel.H> #include "ipmiconfig.H" #include <ipmi/ipmi_reasoncodes.H> @@ -42,6 +44,49 @@ extern trace_desc_t * g_trac_ipmi; #define IPMI_TRAC(printf_string,args...) \ TRACFCOMP(g_trac_ipmi,"sel: "printf_string,##args) +namespace IPMISEL +{ + void sendESEL(uint8_t* i_eselData, uint32_t i_dataSize, + uint32_t i_eid, uint8_t i_eventDirType, + uint8_t i_sensorType, uint8_t i_sensorNumber) + { + IPMI_TRAC(ENTER_MRK "sendESEL()"); + + // one message queue to the SEL thread + static msg_q_t mq = Singleton<IpmiSEL>::instance().msgQueue(); + + msg_t *msg = msg_allocate(); + msg->type = MSG_SEND_ESEL; + msg->data[0] = i_eid; + + // create the sel record of information + IPMISEL::selRecord l_sel; + l_sel.record_type = IPMISEL::record_type_ami_esel; + l_sel.generator_id = IPMISEL::generator_id_ami; + l_sel.evm_format_version = IPMISEL::format_ipmi_version_2_0; + l_sel.sensor_type = i_sensorType; + l_sel.sensor_number = i_sensorNumber; + l_sel.event_dir_type = i_eventDirType; + l_sel.event_data1 = IPMISEL::event_data1_ami; + + eselInitData *eselData = + new eselInitData(&l_sel, i_eselData, i_dataSize); + + msg->extra_data = eselData; + + //Send the msg to the sel thread + int rc = msg_send(mq,msg); + if(rc) + { + IPMI_TRAC(ERR_MRK "Failed (rc=%d) to send message",rc); + delete eselData; + } + IPMI_TRAC(EXIT_MRK "sendESEL"); + return; + } // sendESEL +} // IPMISEL + + /** * @brief Constructor */ @@ -100,8 +145,8 @@ void IpmiSEL::execute(void) switch(msg_type) { - case IPMISEL::MSG_SEND_SEL: - send_sel(msg); + case IPMISEL::MSG_SEND_ESEL: + process_esel(msg); //done with msg msg_free(msg); break; @@ -112,12 +157,11 @@ void IpmiSEL::execute(void) //Respond that we are done shutting down. msg_respond(iv_msgQ, msg); break; - }; - - } + } + } // while(1) IPMI_TRAC(EXIT_MRK "message loop"); return; -} +} // execute /* * @brief Store either Record/Reserve ID from given data @@ -130,9 +174,9 @@ void storeReserveRecord(uint8_t* o_RData, uint8_t* i_data) } /* - * @brief Create Partial Add Header from inputs + * @brief Create Partial Add eSEL Header from inputs */ -void createPAddHeader(uint8_t* i_reserveID, uint8_t* i_recordID, +void createPartialAddHeader(uint8_t* i_reserveID, uint8_t* i_recordID, uint16_t i_offset, uint8_t i_isLastEntry, uint8_t* o_header) { @@ -146,194 +190,215 @@ void createPAddHeader(uint8_t* i_reserveID, uint8_t* i_recordID, return; } +enum esel_retry +{ + MAX_SEND_COUNT = 4, + SLEEP_BASE = 2 * NS_PER_MSEC, +}; + /* - * @brief Send sel msg + * @brief process esel msg */ -void IpmiSEL::send_sel(msg_t *i_msg) +void IpmiSEL::process_esel(msg_t *i_msg) const { - IPMI_TRAC(ENTER_MRK "send_sel"); + errlHndl_t l_err = NULL; + IPMI::completion_code l_cc = IPMI::CC_UNKBAD; + const uint32_t l_eid = i_msg->data[0]; + IPMISEL::eselInitData * l_data = + (IPMISEL::eselInitData*)(i_msg->extra_data); + IPMI_TRAC(ENTER_MRK "process_esel"); + + uint32_t l_send_count = MAX_SEND_COUNT; + while (l_send_count > 0) + { + // try to send the eles to the bmc + send_esel(l_data, l_err, l_cc); - selInitData *l_data = (selInitData*)(i_msg->extra_data); + // if no error but last completion code was: + if ((l_err == NULL) && + ((l_cc == IPMI::CC_BADRESV) || // lost reservation + (l_cc == IPMI::CC_TIMEOUT))) // timeout + { + // update our count and pause + l_send_count--; + if (l_send_count) + { + IPMI_TRAC("process_esel: sleeping; retry_count %d", + l_send_count); + // sleep 3 times - 2ms, 32ms, 512ms. if we can't get this + // through by then, the system must really be busy... + nanosleep(0, + SLEEP_BASE << (4 * (MAX_SEND_COUNT - l_send_count - 1))); + continue; + } + } - size_t eSELlen = i_msg->data[0]; - uint8_t* eSelData[] = {l_data->sel,l_data->eSel,l_data->eSelExtra}; + // else it did get sent down OR it didn't because of a bad error + break; - errlHndl_t err = NULL; - IPMI::completion_code cc = IPMI::CC_UNKBAD; - size_t len = 0; + } // while + + if(l_err) + { + l_err->collectTrace(IPMI_COMP_NAME); + errlCommit(l_err, IPMI_COMP_ID); + } + else if((l_cc == IPMI::CC_OK) && // no error + (l_eid != 0)) // and it's an errorlog + { + // eSEL successfully sent to the BMC - send an ack to the errlmanager + IPMI_TRAC(INFO_MRK "Sending ack for eid 0x%.8X", l_eid); + ERRORLOG::ErrlManager::errlAckErrorlog(l_eid); + } + + delete l_data; + + IPMI_TRAC(EXIT_MRK "process_esel"); + return; +} // process_esel + +/* + * @brief Send esel data to bmc + */ +void IpmiSEL::send_esel(IPMISEL::eselInitData * i_data, + errlHndl_t &o_err, IPMI::completion_code &o_cc) const +{ + IPMI_TRAC(ENTER_MRK "send_esel"); uint8_t* data = NULL; + const size_t l_eSELlen = i_data->dataSize; + + size_t len = 0; uint8_t reserveID[2] = {0,0}; - uint8_t recordID[2] = {0,0}; + uint8_t esel_recordID[2] = {0,0}; + do{ - err = IPMI::sendrecv(IPMI::reserve_sel(),cc,len,data); - if(err) - { - IPMI_TRAC(ERR_MRK "error from reserve sel"); - break; - } - else if (cc != IPMI::CC_OK) - { - IPMI_TRAC(ERR_MRK "Failed to reserve sel, cc is %02x",cc); - break; - } - storeReserveRecord(reserveID,data); + // we need to send down the extended sel data (eSEL), which is + // longer than the protocol buffer, so we need to do a reservation and + // call the AMI partial_add_esel command multiple times + // put a reservation on the SEL Device since we're doing a partial_add + len = 0; delete [] data; - - len = SEL_LENGTH; //16 being the size of one SEL. - cc = IPMI::CC_UNKBAD; - data = new uint8_t[len]; - memcpy(data,eSelData[0],len); - err = IPMI::sendrecv(IPMI::add_sel(),cc,len,data); - if(err) + data = NULL; + o_cc = IPMI::CC_UNKBAD; + o_err = IPMI::sendrecv(IPMI::reserve_sel(),o_cc,len,data); + if(o_err) { - IPMI_TRAC(ERR_MRK "error from add sel"); + IPMI_TRAC(ERR_MRK "error from reserve_sel"); break; } - else if (cc != IPMI::CC_OK) + if(o_cc != IPMI::CC_OK) { - IPMI_TRAC(ERR_MRK "Failed to add sel, cc is %02x",cc); + IPMI_TRAC(ERR_MRK "Failed to reserve_sel, o_cc %02x",o_cc); break; } - storeReserveRecord(recordID,data); + storeReserveRecord(reserveID,data); + // first send down the SEL Event Record data + size_t eSELindex = 0; + uint8_t l_lastEntry = 0; + len = IPMISEL::PARTIAL_ADD_ESEL_REQ + sizeof(IPMISEL::selRecord); delete [] data; - - len = ESEL_META_LEN + SEL_LENGTH; //16: SEL size, 7: size of meta data - cc = IPMI::CC_UNKBAD; data = new uint8_t[len]; - createPAddHeader(reserveID,recordID,0,0x00,data); + // fill in the partial_add_esel request (command) data + createPartialAddHeader(reserveID,esel_recordID,eSELindex,l_lastEntry,data); - memcpy(&data[ESEL_META_LEN],eSelData[1],SEL_LENGTH); + // copy in the SEL event record data + memcpy(&data[IPMISEL::PARTIAL_ADD_ESEL_REQ], i_data->eSel, + sizeof(IPMISEL::selRecord)); - err = IPMI::sendrecv(IPMI::partial_add_esel(),cc,len,data); - if(err) + o_cc = IPMI::CC_UNKBAD; + TRACFBIN( g_trac_ipmi, INFO_MRK"1st partial_add_esel:", data, len); + o_err = IPMI::sendrecv(IPMI::partial_add_esel(),o_cc,len,data); + if(o_err) { - IPMI_TRAC(ERR_MRK "error partial add esel"); + IPMI_TRAC(ERR_MRK "error from first partial_add_esel"); break; } - else if (cc != IPMI::CC_OK) + // as long as we continue to get CC_OK, the reserve sel is good. + // if the reservation is lost (ie, because something else tried to + // create a SEL) then the BMC just discards all this data. the + // errorlog will still be in PNOR and won't get ACKed, so it'll get + // resent on the next IPL. + if (o_cc != IPMI::CC_OK) { - IPMI_TRAC(ERR_MRK "Failed to partial add sel, cc is %02x",cc); + IPMI_TRAC(ERR_MRK "failed first partial_add_esel, o_cc %02x, eSELindex %02x", + o_cc, eSELindex); break; } - storeReserveRecord(recordID,data); + // BMC returns the recordID, it's always the same (unless + // there's a major BMC bug...) + storeReserveRecord(esel_recordID,data); - size_t eSELindex = 0; - while(eSELindex<eSELlen) + // now send down the eSEL data in chunks. + const size_t l_maxBuffer = IPMI::max_buffer(); + while(eSELindex<l_eSELlen) { - if(eSELindex + (IPMI::max_buffer() - ESEL_META_LEN) < eSELlen) - { - len = IPMI::max_buffer(); - } - else - { - len = eSELlen - eSELindex; - } - delete [] data; - data = new uint8_t[len]; - cc = IPMI::CC_UNKBAD; - const uint16_t offset = eSELindex + SEL_LENGTH; - uint8_t dataCpyLen = 0; - //if the index + the maximum buffer is less than what we still //have left in the eSEL, this is not the last entry (data[6] = 0) //otherwise, it is and data[6] = 1 - uint8_t l_lastEntry = 0x00; - if(eSELindex + (IPMI::max_buffer() - ESEL_META_LEN) < eSELlen) + if(eSELindex + (l_maxBuffer - IPMISEL::PARTIAL_ADD_ESEL_REQ) + < l_eSELlen) { + len = l_maxBuffer; l_lastEntry = 0x00; - dataCpyLen = len - ESEL_META_LEN; } else { + len = l_eSELlen - eSELindex + IPMISEL::PARTIAL_ADD_ESEL_REQ; l_lastEntry = 0x01; - dataCpyLen = len; } - createPAddHeader(reserveID,recordID,offset,l_lastEntry,data); - memcpy(&data[ESEL_META_LEN],&eSelData[2][eSELindex],dataCpyLen); + delete [] data; + data = new uint8_t[len]; + + // fill in the partial_add_esel request (command) data + createPartialAddHeader(reserveID, esel_recordID, + eSELindex + sizeof(IPMISEL::selRecord), + l_lastEntry, data); + + uint8_t dataCpyLen = len - IPMISEL::PARTIAL_ADD_ESEL_REQ; + memcpy(&data[IPMISEL::PARTIAL_ADD_ESEL_REQ], + &i_data->eSelExtra[eSELindex], + dataCpyLen); + + // update the offset into the data eSELindex = eSELindex + dataCpyLen; - err = IPMI::sendrecv(IPMI::partial_add_esel(),cc,len,data); - if(err) + o_cc = IPMI::CC_UNKBAD; + TRACFBIN( g_trac_ipmi, INFO_MRK"partial_add_esel:", data, len); + o_err = IPMI::sendrecv(IPMI::partial_add_esel(),o_cc,len,data); + if(o_err) { - IPMI_TRAC(ERR_MRK "error from partial add esel"); + IPMI_TRAC(ERR_MRK "error from partial_add_esel"); break; } - //as long as we continue to get CC_OK, the reserve sel is good. - //the reserve sel is not valid with a 'reservation canceled' CC - else if (cc != IPMI::CC_OK) + // as long as we continue to get CC_OK, the reserve sel is good. + // if the reservation is lost (ie, because something else tried to + // create a SEL) then the BMC just discards all this data. the + // errorlog will still be in PNOR and won't get ACKed, so it'll get + // resent on the next IPL. + if (o_cc != IPMI::CC_OK) { - IPMI_TRAC(ERR_MRK "failed partial add esel, cc is %02x,",cc); - IPMI_TRAC(ERR_MRK "eSELindex is %02x",eSELindex); - //and normally we would have to do some clean up but - //this will break out of the while loop and then hit the - //usual delete messages and then exit the function. + IPMI_TRAC(ERR_MRK "failed partial_add_esel, o_cc %02x, eSELindex %02x", + o_cc, eSELindex); break; } - storeReserveRecord(recordID,data); + // BMC returns the recordID, it's always the same (unless + // there's a major BMC bug...) + storeReserveRecord(esel_recordID,data); } - if(err || cc != IPMI::CC_OK) + if(o_err || (o_cc != IPMI::CC_OK)) { break; } }while(0); - if(err) - { - err->collectTrace(IPMI_COMP_NAME); - errlCommit(err, IPMI_COMP_ID); - } - - delete[] l_data; delete[] data; - IPMI_TRAC(EXIT_MRK "send_sel"); + IPMI_TRAC(EXIT_MRK "send_esel (o_err %.8X, o_cc x%.2x, recID=x%x%x)", + o_err ? o_err->plid() : NULL, o_cc, esel_recordID[1], esel_recordID[0]); return; -} - -namespace IPMISEL -{ - void sendData(uint8_t* i_SEL, uint8_t* i_eSEL, - uint8_t* i_extraData, size_t i_dataSize) - { - IPMI_TRAC(ENTER_MRK "sendData()"); - - // one message queue to the SEL thread - static msg_q_t mq = Singleton<IpmiSEL>::instance().msgQueue(); - - //will eventually send SEL info this way. - msg_t *msg = msg_allocate(); - msg->type = MSG_SEND_SEL; - msg->data[0] = i_dataSize; - - selInitData *selData = new selInitData; - - memcpy(selData->sel, i_SEL, SEL_LENGTH); - memcpy(selData->eSel,i_eSEL,SEL_LENGTH); - //2048 being the max size for eSELExtra - if(i_dataSize > 2048) - { - memcpy(selData->eSelExtra, i_extraData, 2048); - } - else - { - memcpy(selData->eSelExtra, i_extraData, i_dataSize); - } - msg->extra_data = selData; - - //Send the msg to the sel thread - int rc =msg_send(mq,msg); - - if(rc) - { - IPMI_TRAC(ERR_MRK "Failed (rc=%d) to send message",rc); - delete selData; - } - IPMI_TRAC(EXIT_MRK "sendData"); - return; - } -} +} // send_esel diff --git a/src/usr/ipmi/ipmisel.H b/src/usr/ipmi/ipmisel.H deleted file mode 100644 index de9893e85..000000000 --- a/src/usr/ipmi/ipmisel.H +++ /dev/null @@ -1,115 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/usr/ipmi/ipmisel.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 __IPMI_IPMISEL_H -#define __IPMI_IPMISEL_H - -/** - * @file ipmisel.H - * @brief IPMI system error log transport definition - */ - -#include <stdint.h> -#include <builtins.h> -#include <ipmi/ipmiif.H> -#include "ipmibt.H" -#include <errl/errlentry.H> - -/** - * - */ - -const uint8_t SEL_LENGTH = 16; -const uint8_t ESEL_META_LEN = 7; - -struct selInitData -{ - uint8_t sel[SEL_LENGTH]; - uint8_t eSel[SEL_LENGTH]; - //2048 being the max length of an eSEL supported by AMI - uint8_t eSelExtra[2048]; -}; - -namespace IPMISEL -{ - void sendData(uint8_t* i_SEL, uint8_t* i_eSEL, - uint8_t* i_extraData, uint32_t i_dataSize); - enum msg_type - { - MSG_SEND_SEL, - MSG_STATE_SHUTDOWN, - MSG_LAST_TYPE = MSG_STATE_SHUTDOWN, - }; -} - - -class IpmiSEL -{ - public: - - /** - * Thread start routine for the resource provider - * @param[in] void*, unused - */ - static void* start(void* unused); - - /** - * Default constructor - */ - IpmiSEL(void); - - /** - * Destructor - */ - ~IpmiSEL(void); - - /** - * @brief Get the message queue associated with this FRU - * @param[in] void - * @return, a msg_q_t which is the message queue - */ - msg_q_t msgQueue(void) - { return iv_msgQ; } - - private: - /** - * Entry point for the SEL transport definition - */ - void execute(void); - - /** - * @brief - * @param[in] i_msg - */ - void send_sel(msg_t *i_msg); - - msg_q_t iv_msgQ; //!< ipmi message queue - - //Disallow copying of this class. - IpmiSEL& operator=(const IpmiSEL&); - IpmiSEL(const IpmiSEL&); -}; - -#endif |