diff options
author | Richard Knight <rjknight@us.ibm.com> | 2014-10-27 18:14:07 -0500 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2014-11-17 12:02:50 -0600 |
commit | c64777ce5b38e87e02850bdbf480b100fe32df45 (patch) | |
tree | 774625afaa3ff2d03e0f4a12514ce1e84721459c | |
parent | 87b7664dd21fe492c0ff70b86ea53a661216663e (diff) | |
download | blackbird-hostboot-c64777ce5b38e87e02850bdbf480b100fe32df45.tar.gz blackbird-hostboot-c64777ce5b38e87e02850bdbf480b100fe32df45.zip |
Update present/functional state for DIMMs/COREs/PROCs
add interfaces to handle updating various sensors
use new interfaces to update sensor state for
DIMM/CORE/PROC targets.
Change-Id: I71a5792f80617b1baa46319565c6742507a0b667
RTC:108827
Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/14207
Tested-by: Jenkins Server
Reviewed-by: Brian H. Horton <brianh@linux.ibm.com>
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
-rw-r--r-- | src/include/usr/ipmi/ipmi_reasoncodes.H | 7 | ||||
-rw-r--r-- | src/include/usr/ipmi/ipmiif.H | 14 | ||||
-rw-r--r-- | src/include/usr/ipmi/ipmisensor.H | 555 | ||||
-rw-r--r-- | src/usr/hwas/common/deconfigGard.C | 24 | ||||
-rw-r--r-- | src/usr/hwas/hostbootIstep.C | 13 | ||||
-rw-r--r-- | src/usr/ipmi/ipmisensor.C | 669 | ||||
-rw-r--r-- | src/usr/ipmi/makefile | 1 | ||||
-rw-r--r-- | src/usr/targeting/common/xmltohb/attribute_types.xml | 4 |
8 files changed, 1281 insertions, 6 deletions
diff --git a/src/include/usr/ipmi/ipmi_reasoncodes.H b/src/include/usr/ipmi/ipmi_reasoncodes.H index 3e66dbcd8..4ac310db3 100644 --- a/src/include/usr/ipmi/ipmi_reasoncodes.H +++ b/src/include/usr/ipmi/ipmi_reasoncodes.H @@ -33,6 +33,7 @@ namespace IPMI { MOD_IPMISRV_SEND = 0x01, // IPMI::send/IPMI::sendrecv MOD_IPMISRV_REPLY = 0x02, // IPMI::respond + MOD_IPMISENSOR = 0x03, // IPMI::sensor }; enum IPMIReasonCode @@ -42,6 +43,12 @@ namespace IPMI RC_INVALID_SEND = IPMI_COMP_ID | 0x03, RC_WAITER_NOT_FOUND = IPMI_COMP_ID | 0x04, RC_ASYNC_BAD_CC = IPMI_COMP_ID | 0x05, + RC_INVALID_SENSOR_CMD = IPMI_COMP_ID | 0x06, + RC_SENSOR_NOT_SETTABLE = IPMI_COMP_ID | 0x07, + RC_EVENT_DATA_NOT_SETTABLE = IPMI_COMP_ID | 0x08, + RC_SENSOR_NOT_PRESENT = IPMI_COMP_ID | 0x09, + RC_SET_SENSOR_FAILURE = IPMI_COMP_ID | 0x0a, + }; }; diff --git a/src/include/usr/ipmi/ipmiif.H b/src/include/usr/ipmi/ipmiif.H index 040244041..5c6bb6ee8 100644 --- a/src/include/usr/ipmi/ipmiif.H +++ b/src/include/usr/ipmi/ipmiif.H @@ -79,6 +79,8 @@ namespace IPMI enum completion_code { CC_OK = 0x00, + CC_CMDSPC1 = 0x80, // command specific completion code + CC_CMDSPC2 = 0x81, // command specific completion code CC_BUSY = 0xc0, CC_INVALID = 0xc1, CC_CMDLUN = 0xc2, @@ -121,16 +123,21 @@ namespace IPMI inline const command_t get_capabilities(void) { return std::make_pair(NETFUN_APP, 0x36); } - // Storage messages inline const command_t set_sel_time(void) { return std::make_pair(NETFUN_STORAGE, 0x49); } - - // Sensor messages + // event messages inline const command_t platform_event(void) { return std::make_pair(NETFUN_SENSOR, 0x02); } + // sensor messages + inline const command_t set_sensor_reading(void) + { return std::make_pair(NETFUN_SENSOR, 0x30); } + + // sensor messages + inline const command_t get_sensor_reading(void) + { return std::make_pair(NETFUN_SENSOR, 0x2D); } // Some helper messages // Used to create an empty message for reception @@ -200,6 +207,7 @@ namespace IPMI */ inline size_t max_buffer(void); + }; // end namespace IPMI #endif diff --git a/src/include/usr/ipmi/ipmisensor.H b/src/include/usr/ipmi/ipmisensor.H new file mode 100644 index 000000000..74e9da09f --- /dev/null +++ b/src/include/usr/ipmi/ipmisensor.H @@ -0,0 +1,555 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/include/usr/ipmi/ipmisensor.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2014 */ +/* [+] 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 ipmisensor.H + * + * @brief Interface for the Sensor class + * + * This header file contains the interfaces for the sensor class which + * is used to handle setting the virtual sensors maintained by the BMC. + */ + +#include <attributeenums.H> +#include <targeting/common/target.H> +#include <errl/errlentry.H> +#include <targeting/common/targetservice.H> +#include <ipmi/ipmiif.H> + +#ifndef __IPMI_IPMISENSOR_H +#define __IPMI_IPMISENSOR_H + +namespace SENSOR +{ + //** Bit definition for set sensor reading cmd operation field + // [7:6] 10b - write given values to event data bytes let BMC handle + // offset in event data 1 when an external event is + // triggered based on the new data. + // [5:4] 10b - a one causes a one in the corresponding position of + // the event assertion bits, zeros are ignored. + // [3:2] 10b - a one causes a one in the corresponding position of + // the event deassertion bits, zeros are ignored. + // [0:1] 01b - write the given value to the sensor reading byte. + // + // default operation = 1010 1001 + static const uint8_t DEFAULT_OPERATION = 0xA9; // see IPMI Spec. "Set + // Sensor Reading and Event + // Status command" for + // details on this byte. + + + // sensors have the range 0x0-0xFE - 0xFF is reserved for invalid sensor + static const uint16_t INVALID_SENSOR = 0xFF; + + /** + * @struct set_sensor_reading_request + * structure holding the data for the set sensor reading command which + * Hostboot will send to the BMC to update sensor status/readings. + * + */ + struct setSensorReadingRequest + { + uint8_t iv_sensor_number; + uint8_t iv_operation; + uint8_t iv_sensor_reading; + uint16_t iv_assertion_mask; + uint16_t iv_deassertion_mask; + uint8_t iv_event_data[3]; + + // constructor for our data set + setSensorReadingRequest() + :iv_sensor_number(0),iv_operation(DEFAULT_OPERATION), + iv_sensor_reading(0), iv_assertion_mask(0), iv_deassertion_mask(0) + { + memset(iv_event_data,0, sizeof(iv_event_data)); + }; + }PACKED; + + + /** + * @enum completionCode + * Sensor specific completion codes, defined in IPMI Spec. + * + */ + enum completionCode + { + CC_SENSOR_READING_NOT_SETTABLE = 0x80, + CC_EVENT_DATA_BYTES_NOT_SETTABLE = 0x81 + }; + + /** + * @enum procStatusSensorOffsets + * Sensor specific completion codes, defined in IPMI Spec. + * + */ + enum procStatusSensorOfffsets + { + PROC_PRESENT = 0x07, + PROC_FUNCTIONAL_OFFSET = 0x08, + }; + + /** + * @enum dimmStatusSensorOffsets + * Dimm specific offsets for status sensor, defined in IPMI Spec. + * + */ + enum dimmStatusSensorOffsets + { + DIMM_PRESENT_OFFSET = 0x06, + DIMM_FUNCTIONAL_OFFSET = 0x04, + }; + + /** + * @class SensorBase + * + * @brief Base class for sensors + * + * @par Detailed Description: + * Provides the base functionality to set IPMI sensor from Hostboot + * including finding the sensor number given a specific target type. + * The constructor takes a SENSOR_NAME and a target pointer. If a null + * is passed in as the target pointer, the system target will be used + * to search for the requested sensor name. + */ + class SensorBase + { + + public: + /** + * @brief Generic base class constructor for sensor objects + * + * @brief Base class for sensor derivation - takes a sensor name, + * and a target* as input. + * + * @par Detailed Description: + */ + SensorBase(TARGETING::SENSOR_NAME i_name, + TARGETING::Target * i_target); + + /** + * @brief Destructor for the base sensor object + * + * Destroys the sensor object and any owned resources, does not + * alter the state on the BMC + * + * @post Sensor object is destroyed, and all resources are + * reclaimed + */ + virtual ~SensorBase(); + + // low level communication to update sensor readings on the BMC + + /** + * @brief write sensor data + * Low level interface to send the set sensor and event data + * reading command to the BMC through the BT interface. + * + * @return Errorlog handle + * + */ + virtual errlHndl_t writeSensorData(); + + /** + * @brief read sensor data + * Low level interface to send get sensor and event data reading + * command to the BMC through the BT interface. + * + * @param[out] o_data - buffer containing the response data from the + * BMC, + * NOTE: caller is responsible for deleting the memory pointed to + * by o_data. + * + * @return Errorlog handle + * + */ + virtual errlHndl_t readSensorData(uint8_t *& o_data); + + + /** + * @brief process completion codes + * Converts completion code values returned from the IPMI + * transport layer into an error log. + * + * @param[in] i_cc - completion code returned from the IPMI + * transport layer. + * + * @return Errorlog handle + * + */ + errlHndl_t processCompletionCode(IPMI::completion_code i_cc); + + /** + * @brief Send set sensor reading and event status command + * Helper function to send the sensor reading to the BMC, this + * command executes synchronously. + * + * @param[inout] io_data - Initially contains the command and data + * to send to the BMC, will hold the BMC + * response when the command returns. + * + * @param[out] o_completion_code - Return value defined by the IPMI + * spec and returned in the message + * from the BMC to indicate if the + * command processing completed + * successfully. + * + * @return Errorlog handle + * + */ + errlHndl_t sendSetSensorReading( + setSensorReadingRequest *& io_data, + IPMI::completion_code& o_completion_code ); + + protected: + + /** + * @brief setup mask for event assertion/deassertion + * + * Translate the passed in offset into a mask for use in + * as an assertion or deassertion mask. + * + * @param[in] = i_offset - offset for event do be signaled + * + * @return eventMask - event status mask with correctly set bit + * matching the offset passed in. + * + */ + static uint16_t setMask( uint8_t i_offset ); + + /** + * @brief return the event offset from an assertion/deassertion mask + * + * Translate the assertion/deassertion mask into the correct event + * offset. + * + * @param[in] = i_mask - offset for event do be signaled + * + * @return offset - offset of the bit which is set in the passed in + * mask. + * + */ + static uint8_t getOffset( uint16_t i_mask ); + + // Name of this sensor, name is used to find the sensor number in + // the IPMI_SENSORS attribute. + TARGETING::SENSOR_NAME iv_name; + + // Target associated with this sensor. + TARGETING::Target * iv_target; + + // data structure for the send sensor reading command. + setSensorReadingRequest * iv_msg; + + private: + //disable default constructor, copy constructor and the assignment + // operator. + SensorBase(); + + SensorBase& operator=(const SensorBase& i_right); + + SensorBase(const SensorBase& thing ); + + // helper function to get sensor number attribute + // of passed in target + uint16_t getSensorNumber(); + + }; + + /** + * @class FirmwareProgressSensor + * + * @brief Specialized sensor class for the firmware progress sensor + * + * @par Detailed Description: + * Provides the functionality needed to set the firmware progress + * virtual sensor maintained by the BMC. + */ + class FirmwareProgressSensor : public SensorBase + { + + public: + + /** + * @enum firmwareProgressPhase + * + * Current firmware progress phase + * + */ + enum firmwareProgressPhase + { + MEMORY_INIT = 0x01, //< isteps 10->14 + SEC_PROCESSOR_INIT = 0x03, //< isteps 15->16 + STARTING_OS = 0x13, //< isteps 17->21 + BASE_INITIALIZATION = 0x14, //< isteps 6-> 9 + PHASE_NA = 0xFF, // Not applicable + + }; + + /** + * @brief Constructor for the FirmwareProgressSensor + * + * The firmware progress sensor is used to update the BMC + * with the current firmware phase. + * The system target holds the IPMI sensor number for this sensor. + * + */ + FirmwareProgressSensor(); + + /** + * @brief destructor for the FirmwareProgressSensor + * + * The firmware progress sensor is used to update the BMC + */ + ~FirmwareProgressSensor(); + + /** + * + * @brief Set the current firmware boot progress phase + * Interface used to update the event status for the system + * firmware progress sensor. phases are defined by the enum + * firmware_progress_phase. Further information can be found in + * the IPMI specification. + * + * @param[in] i_phase - current firmware progress phase. + * + * @return Errorlog handle + * + */ + errlHndl_t setBootProgressPhase(firmwareProgressPhase i_phase); + + private: + // @enum firmwareProgressOfsets + // + // sensor specific offset used to specify that the event which is + // being signaled is for the system firmware progress sensor. + enum firmwareProgressOffsets + { + SYSTEM_FIRMWARE_PROGRESS = 0x02 //< Sensor specific offset + //< for system firmware + //< progress event. + }; + + }; + + /** + * @class HostStatusSensor + * + * @brief Specialized class for the host status sensor. + * + * @par Detailed Description: + * Provides the functionality needed to set the Host_Status sensor also + * known as the ACPI power state. The Host_status sensor is a virtual + * sensor maintained by the BMC, + */ + class HostStatusSensor : public SensorBase + { + public: + + /** + * @enum hostStatus + * enum to define the ACPI power state of the system, this + * sensor will be updated by Hostboot and opal. + */ + enum hostStatus + { + S0_G0_WORKING = 0x00, //< Host up + S5_G2_SOFT_OFF = 0x05, //< Soft power off + LEGACY_ON_STATE = 0x0B //< Host not up, but started + }; + + /** + * @brief Constructor for the HostStatusSensor + * + * The firmware progress sensor is used to update the BMC + * with the current ACIP power state of the system. + * The system target holds the IPMI sensor number for this sensor. + * + */ + HostStatusSensor(); + + /** + * @brief Destructor for the HostStatusSensor + * + */ + ~HostStatusSensor(); + + /** + * + * @brief Set the current HostStatus + * Interface used to update the event status for the ACPI + * power state of the system. States are defined by the enum + * host_status. Further information can be found in the IPMI + * specification. + * + * + * @param[in] i_phase - current firmware progress phase. + * + * @return Errorlog handle + * + */ + errlHndl_t updateHostStatus( hostStatus status ); + + }; + + /** + * @class RebootCountSensor + * + * @brief Specialized class for the system reboot count. + * + * @par Detailed Description: + * Provides the functionality needed to set the reboot count. The + * reboot count is a special sensor maintained by the BMC. + * + * Usage: + * reboot_count_t count = 3; + * RebootCountSensor l_sensor; + * l_sensor.setRebootCount( count ); + * + */ + class RebootCountSensor : public SensorBase + { + + //< reboot count type + typedef uint8_t rebootCount_t; + + public: + + /** + * @brief Constructor for the RebootCountSensor + * + * The reboot count sensor is used to update the reboot count + * sensor maintained by the BMC. + * + * The system target holds the IPMI sensor number for this sensor. + * + */ + RebootCountSensor(); + + /** + * @brief Destructor for the RebootCountSensor + * + */ + ~RebootCountSensor(); + + /** + * @brief Sent a value for the reboot count to the BMC. + * + * @param[in] i_count - new reboot count value. + * + * @return Errorlog handle + * + */ + errlHndl_t setRebootCount( rebootCount_t i_count ); + + }; + + /** + * @class StatusSensor + * + * @brief Specialized class to handle DIMM, PROC and Core status. + * + * @par Detailed Description: + * Provides the functionality needed to set the status of DIMMS, Cores, + * and processors. The object will determine from the Target* what + * sensor offsets should be used, and configure itself accordingly. + */ + + class StatusSensor : public SensorBase + { + + public: + + /** + * @enum statusEnum + * + * enum defining the status of targets which use the + * status sensor to report functional and present states. + */ + enum statusEnum + { + NOT_PRESENT = 0x0000, + PRESENT = 0x0001, + FUNCTIONAL = 0x0002, + PRESENT_FUNCTIONAL = 0x0003, + NON_FUNCTIONAL = 0x0004, + PRESENT_NONFUNCTIONAL = 0x0005, + }; + + /** + * @brief Constructor for a status sensor + * + * The status sensor is used for DIMMS, Cores and Procs. Hostboot + * will update the present and functional state for the status + * sensor associated with each instance of these target types. + * + * + * The IPMI sensor number for these sensors are associated with + * each instance of the DIMM, CORE and Processor targets. + * + */ + StatusSensor( TARGETING::Target * ); + + /** + * @brief Destructor for the StatusSensor + * + */ + ~StatusSensor(); + + errlHndl_t setStatus( statusEnum status ); + + private: + // disable the default constructor + StatusSensor(); + + // internal offset data which is configured based on target type + // used in construction. + uint8_t iv_presentOffset; + uint8_t iv_functionalOffset; + + }; + + /** + * @brief Update DIMM/CORE/Processor status sensors on the BMC. + * Update the present/functional status on the BMC for status sensors + * monitored by Hostboot. The sensor will be updated based on the + * HWAS state of the target. Currently handles DIMM/CORE/PROC present + * and functional status. + * + */ + void updateBMCSensorStatus(void); + + + /** + * Helper function to update the status sensor for a specific target + * type. Currently supports DIMM, CORE and Processor target types. + * + * @param[in] - i_type, target type to set the status for + * + */ + void updateBMCSensorStatus( TARGETING::TYPE i_type ); + + +}; // end namespace + +#endif diff --git a/src/usr/hwas/common/deconfigGard.C b/src/usr/hwas/common/deconfigGard.C index d3d82a141..89ae8d235 100644 --- a/src/usr/hwas/common/deconfigGard.C +++ b/src/usr/hwas/common/deconfigGard.C @@ -39,6 +39,10 @@ #include <targeting/common/commontargeting.H> #include <targeting/common/utilFilter.H> +#include <ipmi/ipmisensor.H> +#include <config.h> + + // Trace definition #define __COMP_TD__ g_trac_deconf @@ -1415,7 +1419,27 @@ void DeconfigGard::_deconfigureTarget( //****************************************************************************** void DeconfigGard::_doDeconfigureActions(Target & i_target) { + // Placeholder for any necessary deconfigure actions + + +#ifdef CONFIG_BMC_IPMI + // set the BMC status for this target + SENSOR::StatusSensor l_sensor( &i_target ); + + // can assume the presence sensor is in the correct state, just + // assert that it is now non functional. + errlHndl_t err = l_sensor.setStatus( SENSOR::StatusSensor::NON_FUNCTIONAL ); + + if(err) + { + HWAS_ERR("Error returned from call to set sensor status for HUID 0x%x", + TARGETING::get_huid( &i_target) ); + err->collectTrace(HWAS_COMP_NAME, 512); + errlCommit(err, HWAS_COMP_ID); + } +#endif + } //****************************************************************************** diff --git a/src/usr/hwas/hostbootIstep.C b/src/usr/hwas/hostbootIstep.C index 5de7a739e..6c33c0a7c 100644 --- a/src/usr/hwas/hostbootIstep.C +++ b/src/usr/hwas/hostbootIstep.C @@ -62,6 +62,10 @@ #include <proc_enable_reconfig.H> + +#include <ipmi/ipmisensor.H> +#include <config.h> + namespace HWAS { @@ -94,8 +98,6 @@ void* host_set_ipl_parms( void *io_pArgs ) TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "host_set_ipl_parms entry" ); errlHndl_t errl = NULL; - // stub -- nothing here currently - TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "host_set_ipl_parms exit" ); return errl; @@ -130,8 +132,13 @@ void* host_discover_targets( void *io_pArgs ) errl = discoverTargets(); } +#ifdef CONFIG_BMC_IPMI + // send DIMM/CORE/PROC sensor status to the BMC + SENSOR::updateBMCSensorStatus(); +#endif + TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, - "host_discover_targets exit" ); + "host_discover_targets exit" ); return errl; } diff --git a/src/usr/ipmi/ipmisensor.C b/src/usr/ipmi/ipmisensor.C new file mode 100644 index 000000000..c6b118850 --- /dev/null +++ b/src/usr/ipmi/ipmisensor.C @@ -0,0 +1,669 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/ipmi/ipmisensor.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2014 */ +/* [+] 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 ipmisensor.C + * @brief IPMI sensor manipulation + */ + +#include <ipmi/ipmisensor.H> +#include <errl/errlentry.H> +#include <errl/errlmanager.H> +#include <targeting/common/target.H> +#include <attributetraits.H> +#include <targeting/common/utilFilter.H> +#include <ipmi/ipmi_reasoncodes.H> +#include <endian.h> + +extern trace_desc_t * g_trac_ipmi; + +namespace SENSOR +{ + // + // Base class for sensor construction. It is expected that this object will + // be used as the base for any additional sensors defined. + // + SensorBase::SensorBase( TARGETING::SENSOR_NAME i_name, + TARGETING::Target * i_target) + :iv_name(i_name) ,iv_target(i_target) + { + // allocate a new message structure to use with our sensors + // this will be the payload for the IPMI send/sendrecv sensor message. + iv_msg = new setSensorReadingRequest; + }; + + // base class destructor + SensorBase::~SensorBase() + { + // The memory allocated for the set sensor reading command is deleted + // by the IPMI transport layer, this delete will get delete the memory + // allocated by the IPMI transport layer which contains the response + // to the set sensor reading command. + if( iv_msg ) + { + delete[] iv_msg; + } + }; + + // + // Helper function to process completion codes returned from the BMC. + // If the completion code warrants a PEL the function will build and + // return an error log with the correct data captured. + // + errlHndl_t SensorBase::processCompletionCode( IPMI::completion_code i_rc ) + { + errlHndl_t l_err = NULL; + + IPMI::IPMIReasonCode l_reasonCode; + + if( i_rc != IPMI::CC_OK ) + { + // bad rc from the BMC + TRACFCOMP(g_trac_ipmi,"completion code 0x%x returned from the BMC" + " , creating error log", i_rc); + + switch(i_rc) + { + case SENSOR::CC_SENSOR_READING_NOT_SETTABLE: + { + /* @errorlog tag + * @errortype ERRL_SEV_UNRECOVERABLE + * @moduleid IPMI::MOD_IPMISENSOR + * @reasoncode IPMI::RC_SENSOR_NOT_SETTABLE + * @userdata1 BMC IPMI Completion code. + * @userdata2 bytes [0-3]sensor number + * bytes [4-7]HUID of target. + * @devdesc Set sensor reading command failed. + */ + l_reasonCode = IPMI::RC_SENSOR_NOT_SETTABLE; + TRACFCOMP(g_trac_ipmi,"Attempt to change sensor reading or" + "set/clear status bits that are not settable" + " via this command"); + break; + } + + case SENSOR::CC_EVENT_DATA_BYTES_NOT_SETTABLE: + { + /* @errorlog tag + * @errortype ERRL_SEV_UNRECOVERABLE + * @moduleid IPMI::MOD_IPMISENSOR + * @reasoncode IPMI::RC_EVENT_DATA_NOT_SETTABLE + * @userdata1 BMC IPMI Completion code. + * @userdata2 bytes[0-3]sensor number + * bytes[4-7]HUID of target. + * @devdesc Set sensor reading command failed. + */ + l_reasonCode = IPMI::RC_EVENT_DATA_NOT_SETTABLE; + TRACFCOMP(g_trac_ipmi,"Attempted to set event data bytes but" + "setting event data bytes is not supported for" + " this sensor"); + break; + } + + case IPMI::CC_CMDSENSOR: + { + /* @errorlog tag + * @errortype ERRL_SEV_UNRECOVERABLE + * @moduleid IPMI::MOD_IPMISENSOR + * @reasoncode IPMI::RC_INVALID_SENSOR_CMD + * @userdata1 BMC IPMI Completion code. + * @userdata2 bytes [0-3]sensor number + * bytes [4-7]HUID of target. + * @devdesc Command not valid for this sensor. + */ + l_reasonCode = IPMI::RC_INVALID_SENSOR_CMD; + TRACFCOMP(g_trac_ipmi,"Command not valid for this sensor"); + break; + } + + case IPMI::CC_BADSENSOR: + { + /* @errorlog tag + * @errortype ERRL_SEV_UNRECOVERABLE + * @moduleid IPMI::MOD_IPMISENSOR + * @reasoncode IPMI::RC_SENSOR_NOT_PRESENT + * @userdata1 BMC IPMI Completion code. + * @userdata2 bytes [0-3]sensor number + * bytes [4-7]HUID of target. + * @devdesc Requested sensor is not present. + */ + l_reasonCode = IPMI::RC_SENSOR_NOT_PRESENT; + TRACFCOMP(g_trac_ipmi,"Requested sensor not present"); + break; + } + + default: + { + // lump everything else into a general failure for + // now. + /* @errorlog tag + * @errortype ERRL_SEV_UNRECOVERABLE + * @moduleid IPMI::MOD_IPMISENSOR + * @reasoncode IPMI::RC_SET_SENSOR_FAILURE + * @userdata1 BMC IPMI Completion code. + * @userdata2 bytes [0-3]sensor number + * bytes [4-7]HUID of target. + * @devdesc Set sensor reading command failed. + */ + TRACFCOMP(g_trac_ipmi,"Set sensor reading command failed"); + l_reasonCode = IPMI::RC_SET_SENSOR_FAILURE; + break; + } + } + // shift the sensor number into to bytes 0-3 and then + // or in the HUID to bytes 4-7 + uint64_t userdata2 = getSensorNumber(); + + userdata2 = (userdata2 << 32) | TARGETING::get_huid(iv_target); + + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + IPMI::MOD_IPMISENSOR, + l_reasonCode, + i_rc, userdata2, true); + + l_err->collectTrace(IPMI_COMP_NAME); + + } + + return l_err; + } + + // + // Helper function to send the data to the BMC using the correct interface + // protocol + // + errlHndl_t SensorBase::writeSensorData() + { + + errlHndl_t l_err = NULL; + + iv_msg->iv_sensor_number = getSensorNumber(); + + if( iv_msg->iv_sensor_number != INVALID_SENSOR ) + { + + IPMI::completion_code l_rc = IPMI::CC_UNKBAD; + + // iv_msg is deleted by the destructor + l_err = sendSetSensorReading( iv_msg, l_rc); + + if( l_err ) + { + TRACFCOMP(g_trac_ipmi,"error returned from " + "sendSetSensorReading() for sensor number 0x%x", + getSensorNumber()); + + // return error log to caller + } + else + { + // check the completion code to see if we need to generate a + // PEL. + l_err = processCompletionCode( l_rc ); + } + } + else + { + TRACFCOMP(g_trac_ipmi,"We were not able to find a sensor number in" + " the IPMI_SENSORS attribute for sensor_name=0x%x" + "for target with huid=0x%x, skipping call to " + "sendSetSensorReading()", + iv_name, TARGETING::get_huid( iv_target )); + + assert(false); + + } + + return l_err; + }; + + // + // Helper function to set the bit in the assertion/deassertion mask + // associated with the desired sensor specific offset + // + uint16_t SensorBase::setMask( const uint8_t offset ) + { + const uint16_t mask = (0x0001 << offset); + + // need to byte swap the mask (see set sensor reading in spec) + return le16toh(mask); + }; + + // + // Helper function to translate the assertion/deassertion mask into + // the correct event offset. + // + uint8_t SensorBase::getOffset( uint16_t mask ) + { + // $TODO RTC:117872 + return 0; + }; + + // read data from the sensor. + errlHndl_t SensorBase::readSensorData(uint8_t *& o_data) + { + + // get sensor reading command only requires one byte of extra data, + // which will be the sensor number, the command will return between + // 3 and 5 bytes of data. + size_t len = 1; + + // need to allocate some me to hold the sensor number this will be + // deleted by the IPMI transport layer + o_data = new uint8_t[len]; + + o_data[0] = getSensorNumber(); + + IPMI::completion_code cc = IPMI::CC_UNKBAD; + + // o_data will hold the response when this returns + errlHndl_t l_err = sendrecv(IPMI::get_sensor_reading(), cc, len, + (uint8_t *&)o_data); + + // if we didn't get an error back from the BT interface, but see a + // bad completion code from the BMC, process the CC to see if we + // need to create a PEL + if( (l_err == NULL ) && (cc != IPMI::CC_OK) ) + { + l_err = processCompletionCode( cc ); + } + + return l_err; + }; + + // + // Synchronously send a set sensor reading command to the BMC, + // the response is returned with the io_data pointer + // + errlHndl_t SensorBase::sendSetSensorReading( + setSensorReadingRequest *& io_data, + IPMI::completion_code& o_completion_code ) + { + + size_t l_len = sizeof( setSensorReadingRequest ); + + o_completion_code = IPMI::CC_UNKBAD; + + // i_data will hold the response when this returns + errlHndl_t l_err = sendrecv(IPMI::set_sensor_reading(), + o_completion_code, l_len, (uint8_t *&)io_data); + + return l_err; + } + + + // given an array[][2] compare the number in the first column to the passed + // in key value + static inline bool compare_it( uint16_t (&a)[2], uint16_t key ) + { + return a[0] < key; + }; + + // + // Helper function to search the sensor data for the correct sensor number + // based on the sensor name. + // + uint16_t SensorBase::getSensorNumber() + { + + uint16_t l_sensor_number = INVALID_SENSOR; + + if( iv_target == NULL ) + { + // use the system target + TARGETING::targetService().getTopLevelTarget(iv_target); + + // die if there is no system target + assert(iv_target); + + } + + TARGETING::AttributeTraits<TARGETING::ATTR_IPMI_SENSORS>::Type + l_sensors; + + if( iv_target->tryGetAttr<TARGETING::ATTR_IPMI_SENSORS>(l_sensors) ) + { + + // get the number of rows by dividing the total size by the size of + // the first row + uint16_t array_rows = (sizeof(l_sensors)/sizeof(l_sensors[0])); + + // create an iterator pointing to the first element of the array + uint16_t (*begin)[2] = &l_sensors[0]; + + // using the number entries as the index into the array will set the + // end iterator to the correct position or one entry past the last + // element of the array + uint16_t (*end)[2] = &l_sensors[array_rows]; + + uint16_t (*ptr)[2] = + std::lower_bound(begin, end, iv_name, &compare_it); + + // we have not reached the end of the array and the iterator + // returned from lower_bound is pointing to an entry which equals + // the one we are searching for. + if( ( ptr != end ) && ( (*ptr)[0] == iv_name ) ) + { + // found it + l_sensor_number = (*ptr)[1]; + + TRACFCOMP(g_trac_ipmi,"Found sensor number %d for HUID=0x%x", + l_sensor_number, TARGETING::get_huid(iv_target)); + } + } + else + { + // bug here... + assert(0,"no IPMI_SENSOR attribute check target HUID=0x%x", + TARGETING::get_huid(iv_target)); + } + + return l_sensor_number; + } + + /// + // FirmwareProgressSensor constructor - uses system target + // + FirmwareProgressSensor::FirmwareProgressSensor( ) + :SensorBase(TARGETING::SENSOR_NAME_FW_BOOT_PROGRESS, NULL) + { + // message buffer created and initialized in base object. + + // assert the system firmware progress offset. + iv_msg->iv_assertion_mask = setMask( SYSTEM_FIRMWARE_PROGRESS ); + }; + + // + // FirmwareProgressSensor destructor + // + FirmwareProgressSensor::~FirmwareProgressSensor( ) + { + + }; + + + // + // setBootProgressPhase - update the boot progress sensor of the BMC + // + errlHndl_t FirmwareProgressSensor::setBootProgressPhase( + firmwareProgressPhase phase ) + { + // event data 2 holds the progress info + iv_msg->iv_event_data[1] = phase; + + return writeSensorData(); + }; + + // + // RebootCountSensor constructor - uses system target + // + RebootCountSensor::RebootCountSensor() + :SensorBase(TARGETING::SENSOR_NAME_REBOOT_COUNT, NULL) + { + // message buffer created and initialized in base object. + } + + // + // RebootCountSensor destructor + // + RebootCountSensor::~RebootCountSensor(){}; + + // + // setRebootCount - send a new value for the reboot count to the BMC. + // + errlHndl_t RebootCountSensor::setRebootCount( rebootCount_t i_count ) + { + + // put the reboot count into the sensor + // reading byte of the message + iv_msg->iv_sensor_reading = i_count; + + return writeSensorData(); + + } + + // + // StatusSensor constructor - uses system DIMM/CORE/PROC target + // + StatusSensor::StatusSensor( TARGETING::Target * i_target ) + :SensorBase(TARGETING::SENSOR_NAME_STATE, i_target) + { + + switch ( i_target->getAttr<TARGETING::ATTR_TYPE>() ) + { + case TARGETING::TYPE_DIMM: + { + iv_functionalOffset = 0x04; + iv_presentOffset = 0x06; + break; + } + + case TARGETING::TYPE_PROC: + case TARGETING::TYPE_CORE: + { + iv_functionalOffset = 0x08; + iv_presentOffset = 0x07; + break; + } + + default: + iv_presentOffset = 0xFF; + iv_functionalOffset = 0xFF; + break; + } + + }; + + // + // StatusSensor destructor + // + // + StatusSensor::~StatusSensor() + {}; + + + // Convert the input status to the correct sensor offset value, then + // send the message to the BMC to update the event status for this sensor. + errlHndl_t StatusSensor::setStatus( statusEnum i_state ) + { + + errlHndl_t l_err = NULL; + // if the offset isn't configured then the target does not have + // one of these sensors. + if( iv_functionalOffset != 0xFF && iv_presentOffset != 0xFF ) + { + + uint16_t func_mask = setMask( iv_functionalOffset ); + uint16_t pres_mask = setMask( iv_presentOffset ); + + switch ( i_state ) + { + case NOT_PRESENT: + // turn off the present bit + iv_msg->iv_deassertion_mask = pres_mask; + // turn on the disabled bit + iv_msg->iv_assertion_mask = func_mask; + break; + + case PRESENT: + // turn on the present bit + iv_msg->iv_assertion_mask = pres_mask; + break; + + case FUNCTIONAL: + // turn off the disabled bit + iv_msg->iv_deassertion_mask = func_mask; + break; + + case PRESENT_FUNCTIONAL: + // assert the present bit + iv_msg->iv_assertion_mask = pres_mask; + // turn off the disabled bit + iv_msg->iv_deassertion_mask = func_mask; + break; + + case PRESENT_NONFUNCTIONAL: + // assert the present bit + iv_msg->iv_assertion_mask = pres_mask; + // assert the disabled bit + iv_msg->iv_assertion_mask |= func_mask; + break; + + case NON_FUNCTIONAL: + // assert the disabled bit + iv_msg->iv_assertion_mask = func_mask; + break; + + default: + // mark as not present + iv_msg->iv_deassertion_mask = pres_mask; + iv_msg->iv_assertion_mask = func_mask; + break; + } + + l_err = writeSensorData(); + + } + + return l_err; + + }; + + + // + // HostStausSensor constructor - uses system target + // + // + HostStatusSensor::HostStatusSensor() + :SensorBase(TARGETING::SENSOR_NAME_HOST_STATUS, NULL) + { + + }; + + // + // HostStatusSensor destructor + // + // + HostStatusSensor::~HostStatusSensor(){}; + + // + // updateHostStaus - update the BMC HostStatus sensor with the passed in + // value. + // + // + errlHndl_t HostStatusSensor::updateHostStatus( hostStatus status ) + { + iv_msg->iv_assertion_mask = setMask((uint8_t)status); + + return writeSensorData(); + }; + + // + // Used to update the sensor status for a specific set of target types + // currently supported types are TYPE_DIMM, TYPE_CORE, TYPE_PROC. These + // are virtual sensors where Hostboot updates the present and functional + // states and the BMC maintains the sensor. + // + void updateBMCSensorStatus(TARGETING::TYPE i_type) + { + + TARGETING::TargetHandleList l_tList; + + // get all targets of the passed in type, functional or not + switch( i_type ) + { + case TARGETING::TYPE_PROC: + getAllChips( l_tList, TARGETING::TYPE_PROC, false ); + break; + + case TARGETING::TYPE_DIMM: + getAllLogicalCards( l_tList, TARGETING::TYPE_DIMM, false ); + break; + + case TARGETING::TYPE_CORE: + getAllChiplets( l_tList, TARGETING::TYPE_CORE, false); + break; + + default: + assert(0, "invalid target type for BMC update"); + + } + + // have a list of targets now set the status sensor on the BMC for each + // one. + for(TARGETING::TargetHandleList::const_iterator pTargetIt = + l_tList.begin(); + pTargetIt != l_tList.end(); + ++pTargetIt ) + { + + StatusSensor::statusEnum l_status + = StatusSensor::PRESENT_FUNCTIONAL; + + // create a status sensor for our needs + StatusSensor l_sensor((*pTargetIt)); + + TARGETING::HwasState l_state = + (*pTargetIt)->getAttr<TARGETING::ATTR_HWAS_STATE>(); + + if( l_state.present == true ) + { + if( l_state.functional == false ) + { + l_status = StatusSensor::PRESENT_NONFUNCTIONAL; + } + } + else + { + l_status = StatusSensor::NOT_PRESENT; + } + + // send the status to the BMC + errlHndl_t l_err = l_sensor.setStatus( l_status ); + + // commit the error and move to the next target + if( l_err ) + { + errlCommit( l_err, IPMI_COMP_ID ); + } + } + + } + + void updateBMCSensorStatus() + { + // send status of all DIMM targets + updateBMCSensorStatus(TARGETING::TYPE_DIMM); + + // send status for all PROC targets + updateBMCSensorStatus(TARGETING::TYPE_PROC); + + updateBMCSensorStatus(TARGETING::TYPE_CORE); + + }; + +}; // end name space + + diff --git a/src/usr/ipmi/makefile b/src/usr/ipmi/makefile index 3d8ca3a8c..92cf4362b 100644 --- a/src/usr/ipmi/makefile +++ b/src/usr/ipmi/makefile @@ -30,6 +30,7 @@ OBJS += $(if $(CONFIG_BMC_BT_LPC_IPMI),ipmibt.o) OBJS += ipmirp.o OBJS += $(if $(CONFIG_BMC_BT_LPC_IPMI),ipmidd.o) OBJS += ipmiconfig.o +OBJS += ipmisensor.o #SUBDIRS += test.d diff --git a/src/usr/targeting/common/xmltohb/attribute_types.xml b/src/usr/targeting/common/xmltohb/attribute_types.xml index 1cdf89a4f..31deb9ff3 100644 --- a/src/usr/targeting/common/xmltohb/attribute_types.xml +++ b/src/usr/targeting/common/xmltohb/attribute_types.xml @@ -455,6 +455,10 @@ <name>SYSTEM_FIRMWARE_PROGRESS</name> <value>0x0F</value> </enumerator> + <enumerator> + <name>REBOOT_COUNT</name> + <value>0xC0</value> + </enumerator> </enumerationType> <attribute> |