diff options
Diffstat (limited to 'src/usr/ipmi')
| -rw-r--r-- | src/usr/ipmi/ipmirp.C | 2 | ||||
| -rw-r--r-- | src/usr/ipmi/ipmisel.C | 277 | ||||
| -rw-r--r-- | src/usr/ipmi/makefile | 1 | ||||
| -rw-r--r-- | src/usr/ipmi/runtime/makefile | 37 | ||||
| -rw-r--r-- | src/usr/ipmi/runtime/rt_ipmirp.C | 142 | ||||
| -rw-r--r-- | src/usr/ipmi/runtime/test/makefile | 31 | ||||
| -rw-r--r-- | src/usr/ipmi/runtime/test/rt_ipmitest.H | 102 |
7 files changed, 468 insertions, 124 deletions
diff --git a/src/usr/ipmi/ipmirp.C b/src/usr/ipmi/ipmirp.C index 51b943ab0..50f8ef2b5 100644 --- a/src/usr/ipmi/ipmirp.C +++ b/src/usr/ipmi/ipmirp.C @@ -865,7 +865,7 @@ namespace IPMI IPMI_TRAC("queuing sync %x:%x", ipmi_msg->iv_netfun, ipmi_msg->iv_cmd); int rc = msg_sendrecv(mq, ipmi_msg->iv_msg); - // If the kernel didn't give a hassle about he message, check to see if + // If the kernel didn't give a hassle about the message, check to see if // there was an error reported back from the other end of the queue. If // this message made it to the other end of the queue, then our memory // (io_data) is in the proper state. diff --git a/src/usr/ipmi/ipmisel.C b/src/usr/ipmi/ipmisel.C index df746f011..92a70faa5 100644 --- a/src/usr/ipmi/ipmisel.C +++ b/src/usr/ipmi/ipmisel.C @@ -44,125 +44,7 @@ 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 - */ -IpmiSEL::IpmiSEL(void): - iv_msgQ(msg_q_create()) -{ - IPMI_TRAC(ENTER_MRK "IpmiSEL ctor"); - task_create(&IpmiSEL::start,NULL); -} - -/** - * @brief Destructor - */ -IpmiSEL::~IpmiSEL(void) -{ - msg_q_destroy(iv_msgQ); -} - -void* IpmiSEL::start(void* unused) -{ - Singleton<IpmiSEL>::instance().execute(); - return NULL; -} - -/** - * @brief Entry point of the sel ipmi thread - */ -//@todo: RTC 119832 -void IpmiSEL::execute(void) -{ - //Mark as an independent daemon so if it crashes we terminate. - task_detach(); - - // Register shutdown events with init service. - // Done at the "end" of shutdown processesing. - // This will flush out any IPMI messages which were sent as - // part of the shutdown processing. We chose MBOX priority - // as we don't want to accidentally get this message after - // interrupt processing has stopped in case we need intr to - // finish flushing the pipe. - INITSERVICE::registerShutdownEvent(iv_msgQ, IPMISEL::MSG_STATE_SHUTDOWN, - INITSERVICE::MBOX_PRIORITY); - - while(true) - { - msg_t* msg = msg_wait(iv_msgQ); - - const IPMISEL::msg_type msg_type = - static_cast<IPMISEL::msg_type>(msg->type); - - // Invert the "default" by checking here. This allows the compiler - // to warn us if the enum has an unhadled case but still catch - // runtime errors where msg_type is set out of bounds. - assert(msg_type <= IPMISEL::MSG_LAST_TYPE, - "msg_type %d not handled", msg_type); - - switch(msg_type) - { - case IPMISEL::MSG_SEND_ESEL: - process_esel(msg); - //done with msg - msg_free(msg); - break; - - case IPMISEL::MSG_STATE_SHUTDOWN: - IPMI_TRAC(INFO_MRK "ipmisel shutdown event"); - - //Respond that we are done shutting down. - msg_respond(iv_msgQ, msg); - break; - } - } // while(1) - IPMI_TRAC(EXIT_MRK "message loop"); - return; -} // execute - +// local functions /* * @brief Store either Record/Reserve ID from given data */ @@ -196,10 +78,63 @@ enum esel_retry SLEEP_BASE = 2 * NS_PER_MSEC, }; + +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()"); + +#ifdef __HOSTBOOT_RUNTIME + // HBRT doesn't send a msg, but use the msg structure to pass the data + msg_t l_msg; + msg_t *msg = &l_msg; + memset(msg, 0, sizeof(msg_t)); +#else + msg_t *msg = msg_allocate(); +#endif + 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; + +#ifdef __HOSTBOOT_RUNTIME + process_esel(msg); +#else + // one message queue to the SEL thread + static msg_q_t mq = Singleton<IpmiSEL>::instance().msgQueue(); + + //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; + } +#endif + IPMI_TRAC(EXIT_MRK "sendESEL"); + return; +} // sendESEL + /* * @brief process esel msg */ -void IpmiSEL::process_esel(msg_t *i_msg) const +void process_esel(msg_t *i_msg) { errlHndl_t l_err = NULL; IPMI::completion_code l_cc = IPMI::CC_UNKBAD; @@ -212,7 +147,7 @@ void IpmiSEL::process_esel(msg_t *i_msg) const while (l_send_count > 0) { // try to send the eles to the bmc - send_esel(l_data, l_err, l_cc); + IPMISEL::send_esel(l_data, l_err, l_cc); // if no error but last completion code was: if ((l_err == NULL) && @@ -240,15 +175,31 @@ void IpmiSEL::process_esel(msg_t *i_msg) const if(l_err) { +#ifdef __HOSTBOOT_RUNTIME + // HBRT can't commit an error, since this could already be in the + // errlCommit path since HBRT is single threaded + IPMI_TRAC(ERR_MRK "DELETING l_err 0x%.8X", l_err->eid()); + delete l_err; + l_err = NULL; + + // TODO RTC: 123419 investigate adding a 'iv_isIpmiEnabled' flag and setting + // that to false somehow, so that we can commit error logs in this path + // and future calls wont try to send them down. +#else l_err->collectTrace(IPMI_COMP_NAME); errlCommit(l_err, IPMI_COMP_ID); +#endif } else if((l_cc == IPMI::CC_OK) && // no error (l_eid != 0)) // and it's an errorlog { +#ifdef __HOSTBOOT_RUNTIME + // TODO RTC: 123419 story to add storing errlog to PNOR in HBRT if IPMI +#else // 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); +#endif } delete l_data; @@ -260,8 +211,8 @@ void IpmiSEL::process_esel(msg_t *i_msg) const /* * @brief Send esel data to bmc */ -void IpmiSEL::send_esel(IPMISEL::eselInitData * i_data, - errlHndl_t &o_err, IPMI::completion_code &o_cc) const +void send_esel(IPMISEL::eselInitData * i_data, + errlHndl_t &o_err, IPMI::completion_code &o_cc) { IPMI_TRAC(ENTER_MRK "send_esel"); uint8_t* data = NULL; @@ -402,3 +353,83 @@ void IpmiSEL::send_esel(IPMISEL::eselInitData * i_data, return; } // send_esel +} // IPMISEL + +#ifndef __HOSTBOOT_RUNTIME +/** + * @brief Constructor + */ +IpmiSEL::IpmiSEL(void) + :iv_msgQ(msg_q_create()) +{ + IPMI_TRAC(ENTER_MRK "IpmiSEL ctor"); + task_create(&IpmiSEL::start,NULL); +} + +/** + * @brief Destructor + */ +IpmiSEL::~IpmiSEL(void) +{ + msg_q_destroy(iv_msgQ); +} + +void* IpmiSEL::start(void* unused) +{ + Singleton<IpmiSEL>::instance().execute(); + return NULL; +} + +/** + * @brief Entry point of the sel ipmi thread + */ +//@todo: RTC 119832 +void IpmiSEL::execute(void) +{ + //Mark as an independent daemon so if it crashes we terminate. + task_detach(); + + // Register shutdown events with init service. + // Done at the "end" of shutdown processesing. + // This will flush out any IPMI messages which were sent as + // part of the shutdown processing. We chose MBOX priority + // as we don't want to accidentally get this message after + // interrupt processing has stopped in case we need intr to + // finish flushing the pipe. + INITSERVICE::registerShutdownEvent(iv_msgQ, IPMISEL::MSG_STATE_SHUTDOWN, + INITSERVICE::MBOX_PRIORITY); + + while(true) + { + msg_t* msg = msg_wait(iv_msgQ); + + const IPMISEL::msg_type msg_type = + static_cast<IPMISEL::msg_type>(msg->type); + + // Invert the "default" by checking here. This allows the compiler + // to warn us if the enum has an unhadled case but still catch + // runtime errors where msg_type is set out of bounds. + assert(msg_type <= IPMISEL::MSG_LAST_TYPE, + "msg_type %d not handled", msg_type); + + switch(msg_type) + { + case IPMISEL::MSG_SEND_ESEL: + IPMISEL::process_esel(msg); + //done with msg + msg_free(msg); + break; + + case IPMISEL::MSG_STATE_SHUTDOWN: + IPMI_TRAC(INFO_MRK "ipmisel shutdown event"); + + //Respond that we are done shutting down. + msg_respond(iv_msgQ, msg); + break; + } + } // while(1) + IPMI_TRAC(EXIT_MRK "message loop"); + return; +} // execute +#endif + diff --git a/src/usr/ipmi/makefile b/src/usr/ipmi/makefile index 8dad57f3e..fb6a249a4 100644 --- a/src/usr/ipmi/makefile +++ b/src/usr/ipmi/makefile @@ -39,6 +39,7 @@ OBJS += ipmipowerstate.o OBJS += ipmiselrecord.o OBJS += ipmidcmi.o +SUBDIRS += runtime.d #SUBDIRS += test.d include ${ROOTPATH}/config.mk diff --git a/src/usr/ipmi/runtime/makefile b/src/usr/ipmi/runtime/makefile new file mode 100644 index 000000000..21ab138ff --- /dev/null +++ b/src/usr/ipmi/runtime/makefile @@ -0,0 +1,37 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/ipmi/runtime/makefile $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 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 +HOSTBOOT_RUNTIME = 1 +ROOTPATH = ../../../.. +MODULE = ipmi_rt + +OBJS += ipmisel.o +OBJS += ipmisensor.o +OBJS += rt_ipmirp.o + +SUBDIRS += test.d + +VPATH += .. +include $(ROOTPATH)/config.mk + diff --git a/src/usr/ipmi/runtime/rt_ipmirp.C b/src/usr/ipmi/runtime/rt_ipmirp.C new file mode 100644 index 000000000..7184c85f7 --- /dev/null +++ b/src/usr/ipmi/runtime/rt_ipmirp.C @@ -0,0 +1,142 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/ipmi/runtime/rt_ipmirp.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 */ +/** + * @file rt_ipmirp.C + * @brief IPMI resource provider definition for runtime + */ + +#include "../ipmirp.H" +#include "../ipmiconfig.H" +#include "../ipmidd.H" +#include <ipmi/ipmi_reasoncodes.H> +#include <ipmi/ipmiif.H> + +#include <config.h> +#include <sys/task.h> +#include <initservice/taskargs.H> +#include <initservice/initserviceif.H> +#include <sys/vfs.h> + +#include <targeting/common/commontargeting.H> +#include <kernel/ipc.H> +#include <arch/ppc.H> +#include <errl/errlmanager.H> +#include <sys/time.h> +#include <sys/misc.h> +#include <errno.h> +#include <runtime/interface.h> + +trace_desc_t * g_trac_ipmi; +#define IPMI_TRAC(printf_string,args...) \ + TRACFCOMP(g_trac_ipmi,"rt: "printf_string,##args) + +namespace IPMI +{ + // TODO RTC: 124099 move to a _hb attribute + // ATTR_IPMI_MAX_BUFFER_SEND_SIZE + static const size_t g_max_buffer = 61; + size_t max_buffer(void) + { + return g_max_buffer; + } + + /// + /// @brief Synchronus message send + /// + errlHndl_t sendrecv(const IPMI::command_t& i_cmd, + IPMI::completion_code& o_completion_code, + size_t& io_len, uint8_t*& io_data) + { + errlHndl_t err = NULL; + int rc = 0; + + // if the buffer is too large this is a programming error. + assert(io_len <= g_max_buffer); + + IPMI_TRAC("calling sync %x:%x len=%d", + i_cmd.first, i_cmd.second, io_len); + + if(g_hostInterfaces && g_hostInterfaces->ipmi_msg) + { + size_t l_len = g_max_buffer; // max size the BMC can return + uint8_t *l_data = new uint8_t[l_len]; + + rc = g_hostInterfaces->ipmi_msg( + i_cmd.first, i_cmd.second, + io_data, io_len, + l_data, &l_len); + + if(rc) + { + IPMI_TRAC(ERR_MRK + "Failed sending ipmi msg (%x:%x) to bmc rc: %d. ", + i_cmd.first, i_cmd.second, rc); + + /* @errorlog tag + * @errortype ERRL_SEV_UNRECOVERABLE + * @moduleid IPMI::MOD_IPMIRT + * @reasoncode IPMI::RC_INVALID_SENDRECV + * @userdata1[0:31] rc from ipmi_msg() + * @userdata1[32:46] netfn of failing msg + * @userdata1[47:63] cmd of failing msg + * @userdata2 length of failing msg + * @devdesc ipmi_msg() failed + * @custdesc Firmware error + */ + err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + IPMI::MOD_IPMIRT, + IPMI::RC_INVALID_SENDRECV, + TWO_UINT32_TO_UINT64(rc, + TWO_UINT16_TO_UINT32(i_cmd.first, i_cmd.second)), + io_len, + true); + err->collectTrace(IPMI_COMP_NAME); + delete[] io_data; + io_data = NULL; + io_len = 0; + } + else + { + // clean up the memory for the caller + o_completion_code = static_cast<IPMI::completion_code>(io_data[0]); + + // now need to create the buffer to return + io_len = l_len - 1; // get rid of the completion_code + delete[] io_data; + io_data = new uint8_t[io_len]; + memcpy(io_data, &l_data[1], io_len); // data after CC + } + delete[] l_data; + } + else + { + IPMI_TRAC(ERR_MRK + "Host interfaces not initialized; ipmi msg not sent. "); + } + + return err; + } // sendrecv +}; diff --git a/src/usr/ipmi/runtime/test/makefile b/src/usr/ipmi/runtime/test/makefile new file mode 100644 index 000000000..a12933112 --- /dev/null +++ b/src/usr/ipmi/runtime/test/makefile @@ -0,0 +1,31 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/ipmi/runtime/test/makefile $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 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 +HOSTBOOT_RUNTIME = 1 +ROOTPATH = ../../../../.. + +MODULE = testipmi_rt +TESTS = *.H + +include ${ROOTPATH}/config.mk diff --git a/src/usr/ipmi/runtime/test/rt_ipmitest.H b/src/usr/ipmi/runtime/test/rt_ipmitest.H new file mode 100644 index 000000000..b3a252e31 --- /dev/null +++ b/src/usr/ipmi/runtime/test/rt_ipmitest.H @@ -0,0 +1,102 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/ipmi/runtime/test/rt_ipmitest.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 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 __RT_IPMITEST_H +#define __RT_IPMITEST_H + +/** + * @file ipmitest.H + * + * @brief Test case for IPMI messages +*/ + +#include <cxxtest/TestSuite.H> + +#include "../../../trace/entry.H" + +#include <ipmi/ipmiif.H> +#include <ipmi/ipmisensor.H> + + +class RT_IpmiTest: public CxxTest::TestSuite +{ +public: + + + /** + * @brief call sendrecv directly + */ + void testIpmi1(void) + { + do + { + IPMI::completion_code cc = IPMI::CC_UNKBAD; + size_t len = 0; + uint8_t* data = NULL; + errlHndl_t err = IPMI::sendrecv(IPMI::get_capabilities(), cc, len, data); + + TS_WARN("testIpmi1: cc x%x, len %d", cc, len); + + if ( err != NULL ) + { + TS_FAIL("testIpmi1: get_capabilities() failed"); + break; + } + if (cc != IPMI::CC_OK) + { + TS_FAIL("testIpmi1: get_capabilities() failed with cc 0x%x", cc); + break; + } + if (len != 5) + { + TS_FAIL("testIpmi1: get_capabilities() returned len %d instead of 5", + len); + break; + } + + TS_WARN("testIpmi1: get_capabilities x%x, x%x x%x x%x x%x", + data[0], data[1], data[2], data[3], data[4]); + + } + while(0); + } + + /** + * @brief call IPMI::sensor function + */ + void testIpmi2(void) + { + do + { + uint8_t l_sensorNumber = SENSOR::getFaultSensorNumber( + TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL); + + TS_WARN("testIpmi2: getFaultSensorNumber x%x", + l_sensorNumber); + } + while(0); + } +}; + +#endif |

