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/usr | |
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/usr')
-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 |
4 files changed, 316 insertions, 335 deletions
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 |