summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/include/usr/ipmi/ipmi_reasoncodes.H1
-rw-r--r--src/include/usr/ipmi/ipmisensor.H98
-rw-r--r--src/usr/ipmi/ipmisensor.C211
3 files changed, 244 insertions, 66 deletions
diff --git a/src/include/usr/ipmi/ipmi_reasoncodes.H b/src/include/usr/ipmi/ipmi_reasoncodes.H
index 2df631f42..6244b2d00 100644
--- a/src/include/usr/ipmi/ipmi_reasoncodes.H
+++ b/src/include/usr/ipmi/ipmi_reasoncodes.H
@@ -51,6 +51,7 @@ namespace IPMI
RC_SET_SENSOR_FAILURE = IPMI_COMP_ID | 0x0a,
RC_READ_EVENT_FAILURE = IPMI_COMP_ID | 0x0b,
RC_DCMI_CMD_FAILED = IPMI_COMP_ID | 0x0c,
+ RC_SENSOR_READING_NOT_AVAIL = IPMI_COMP_ID | 0x0d,
};
};
diff --git a/src/include/usr/ipmi/ipmisensor.H b/src/include/usr/ipmi/ipmisensor.H
index dfbfcb8ee..13a2532ea 100644
--- a/src/include/usr/ipmi/ipmisensor.H
+++ b/src/include/usr/ipmi/ipmisensor.H
@@ -137,6 +137,28 @@ namespace SENSOR
}PACKED;
/**
+ * @struct getSensorReadingData
+ * structure holding the data returned by the get sensor reading
+ * command.
+ *
+ */
+ struct getSensorReadingData
+ {
+ uint8_t completion_code;
+ uint8_t sensor_status;
+ uint8_t sensor_reading;
+ uint16_t event_status;
+
+ // constructor for our data set
+ getSensorReadingData()
+ :completion_code(0),sensor_status(0),
+ sensor_reading(0), event_status(0)
+ {
+
+ };
+ }PACKED;
+
+ /**
* @enum completionCode
* Sensor specific completion codes, defined in IPMI Spec.
*
@@ -146,6 +168,18 @@ namespace SENSOR
CC_SENSOR_READING_NOT_SETTABLE = 0x80,
CC_EVENT_DATA_BYTES_NOT_SETTABLE = 0x81
};
+ /**
+ * @enum SensorReadingValidEnum
+ *
+ * enum defining masks used when reading a sensor
+ *
+ */
+ enum SensorReadingValidEnum
+ {
+ SENSOR_DISABLED = 0x80,
+ SENSOR_SCANNING_DISABLED = 0x40,
+ READING_UNAVAILABLE = 0x20,
+ };
@@ -212,7 +246,7 @@ namespace SENSOR
* @return Errorlog handle
*
*/
- virtual errlHndl_t readSensorData(uint8_t *& o_data);
+ virtual errlHndl_t readSensorData(getSensorReadingData& o_data);
/**
@@ -251,12 +285,23 @@ namespace SENSOR
IPMI::completion_code& o_completion_code );
/**
+ * @brief helper function to get the sensor nubmer
+ */
+ inline uint8_t getSensorNumber( )
+ {
+ return getSensorNumber(iv_target, iv_name );
+ };
+
+
+ /**
* @brief return the sensor number
*
* @return sensor_number - sensor number for this sensor
*
*/
- uint8_t getSensorNumber();
+ static uint8_t getSensorNumber(TARGETING::Target * i_targ,
+ TARGETING::SENSOR_NAME i_name );
+
protected:
@@ -267,12 +312,16 @@ namespace SENSOR
* as an assertion or deassertion mask.
*
* @param[in] = i_offset - offset for event do be signaled
+ * @param[in] = i_swap - indicates if mask should be
+ * byteswapped before returning
+ * true = byte swap mask
+ * false = do not byte swap the mask
*
* @return eventMask - event status mask with correctly set bit
* matching the offset passed in.
*
*/
- static uint16_t setMask( uint8_t i_offset );
+ static uint16_t setMask( uint8_t i_offset, bool i_swap = true );
/**
* @brief return the event offset from an assertion/deassertion mask
@@ -448,9 +497,6 @@ namespace SENSOR
class RebootCountSensor : public SensorBase
{
- //< reboot count type
- typedef uint8_t rebootCount_t;
-
public:
/**
@@ -471,14 +517,25 @@ namespace SENSOR
~RebootCountSensor();
/**
- * @brief Sent a value for the reboot count to the BMC.
+ * @brief Set the 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 );
+ errlHndl_t setRebootCount( uint16_t i_count );
+
+ /**
+ * @brief get the value of the reboot count from the BMC.
+ *
+ * @param[o] o_rebootCount - new reboot count value.
+ *
+ * @return Errorlog handle
+ *
+ */
+ errlHndl_t getRebootCount( uint16_t& o_rebootCount );
+
};
@@ -668,16 +725,17 @@ namespace SENSOR
public:
/**
- * @enum stateEnum
+ * @enum OccStateEnum
*
* enum defining the state of the OCC sensor
*/
enum OccStateEnum
{
- OCC_ACTIVE = 0x0001,
- OCC_NOT_ACTIVE = 0x0002
+ OCC_NOT_ACTIVE = 0x00,
+ OCC_ACTIVE = 0x01
};
+
/**
* @brief Constructor for an OccActive sensor
*
@@ -695,14 +753,24 @@ namespace SENSOR
*/
~OCCActiveSensor();
+ /**
+ * @brief Interface to set the state of the OCC
+ * active sensor.
+ *
+ */
errlHndl_t setState( OccStateEnum i_state );
+ /**
+ * @brief Interface to determine if the OCC associated
+ * with the passed in target is active.
+ *
+ */
+ bool isActive();
+
private:
// disable the default constructor
OCCActiveSensor();
- uint8_t iv_functionalOffset;
-
};
/*
@@ -745,6 +813,7 @@ namespace SENSOR
* using the dcmi "activate power limit"
* command.
*
+ * @return Errorlog handle
*/
errlHndl_t getUserPowerLimit( uint16_t &o_powerLimit,
bool &o_activeActive );
@@ -758,7 +827,8 @@ namespace SENSOR
* the sensor numbers for each of the 16
* apss channels
*
- * const uint16_t (*array)[16] = NULL;
+ * @return Errorlog handle
+ *
*/
errlHndl_t getAPSSChannelSensorNumbers(
const uint16_t (* &o_sensor_numbers)[16]);
diff --git a/src/usr/ipmi/ipmisensor.C b/src/usr/ipmi/ipmisensor.C
index 4e6a03973..84a7d31de 100644
--- a/src/usr/ipmi/ipmisensor.C
+++ b/src/usr/ipmi/ipmisensor.C
@@ -35,7 +35,6 @@
#include <targeting/common/utilFilter.H>
#include <ipmi/ipmi_reasoncodes.H>
#include <endian.h>
-
extern trace_desc_t * g_trac_ipmi;
namespace SENSOR
@@ -115,9 +114,9 @@ namespace SENSOR
* @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");
+ TRACFCOMP(g_trac_ipmi,"Attempted to set event data bytes "
+ "but setting event data bytes is not supported for"
+ " this sensor");
break;
}
@@ -249,12 +248,20 @@ namespace SENSOR
// 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 )
+ uint16_t SensorBase::setMask( const uint8_t offset, bool swap )
{
const uint16_t mask = (0x0001 << offset);
- // need to byte swap the mask (see set sensor reading in spec)
- return le16toh(mask);
+ if(swap)
+ {
+ // need to byte swap the mask (see set sensor reading in spec)
+ return le16toh(mask);
+ }
+ else
+ {
+ return mask;
+ }
+
};
//
@@ -268,7 +275,7 @@ namespace SENSOR
};
// read data from the sensor.
- errlHndl_t SensorBase::readSensorData(uint8_t *& o_data)
+ errlHndl_t SensorBase::readSensorData( getSensorReadingData& o_data)
{
// get sensor reading command only requires one byte of extra data,
@@ -276,26 +283,88 @@ namespace SENSOR
// 3 and 5 bytes of data.
size_t len = 1;
- // need to allocate some me to hold the sensor number this will be
+ // need to allocate some mem to hold the sensor number this will be
// deleted by the IPMI transport layer
- o_data = new uint8_t[len];
+ uint8_t * l_data = new uint8_t[len];
- o_data[0] = getSensorNumber();
+ l_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);
+ l_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) )
+ if( l_err == NULL )
{
l_err = processCompletionCode( cc );
- }
+ // $TODO RTC:123045 - Remove when SDR is finalized
+ if( l_err == NULL && (cc != IPMI::CC_BADSENSOR) )
+ {
+ // populate the output structure with the sensor data
+ o_data.completion_code = cc;
+
+ o_data.sensor_status = l_data[0];
+
+ o_data.sensor_reading = l_data[1];
+
+ // bytes 3-5 of the reading are optional and will be dependent
+ // on the value of the sensor status byte.
+ if( !( o_data.sensor_status &
+ ( SENSOR::SENSOR_DISABLED |
+ SENSOR::SENSOR_SCANNING_DISABLED )) ||
+ ( o_data.sensor_status & SENSOR::READING_UNAVAILABLE ))
+ {
+ // sensor reading is available
+ o_data.event_status =
+ (( (uint16_t) l_data[3]) << 8 | l_data[2] );
+
+ // spec indicates that the high order bit should be
+ // ignored on a read, so lets mask it off now.
+ o_data.event_status &= 0x7FFFF;
+ }
+ else
+ {
+ uint32_t l_sensorNumber = getSensorNumber();
+
+ TRACFCOMP(g_trac_ipmi,"Sensor reading not available: status = 0x%x",o_data.sensor_status);
+ TRACFCOMP(g_trac_ipmi,"sensor number 0x%x, huid 0x%x",l_sensorNumber ,get_huid(iv_target));
+
+ // something happened log an error to indicate the request
+ // failed
+ /* @errorlog tag
+ * @errortype ERRL_SEV_UNRECOVERABLE
+ * @moduleid IPMI::MOD_IPMISENSOR
+ * @reasoncode IPMI::RC_SENSOR_READING_NOT_AVAIL
+ * @userdata1 sensor status indicating reason for
+ * reading not available
+ * @userdata2[0:31] sensor number
+ * @userdata2[32:64] HUID of target
+ *
+ * @devdesc Set sensor reading command failed.
+ * @custdesc Request to get sensor reading
+ * IPMI completion code can be seen
+ * in userdata1 field of the log.
+ */
+ l_err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ IPMI::MOD_IPMISENSOR,
+ IPMI::RC_SENSOR_READING_NOT_AVAIL,
+ o_data.sensor_status,
+ TWO_UINT32_TO_UINT64( l_sensorNumber,
+ TARGETING::get_huid(iv_target)), true);
+
+ l_err->collectTrace(IPMI_COMP_NAME);
+
+ }
+
+ delete[] l_data;
+ }
+ }
return l_err;
};
@@ -399,29 +468,32 @@ namespace SENSOR
return getMajorType(i_sensorRecord[0]) == getMajorType(i_sensorName);
}
+ // $TODO RTC:123035 investigate pre-populating some info if we end up
+ // doing this multiple times per sensor
//
// Helper function to search the sensor data for the correct sensor number
// based on the sensor name.
//
- uint8_t SensorBase::getSensorNumber()
+ uint8_t SensorBase::getSensorNumber( TARGETING::Target * i_targ,
+ TARGETING::SENSOR_NAME i_name )
{
uint8_t l_sensor_number = INVALID_SENSOR;
- if( iv_target == NULL )
+ if( i_targ == NULL )
{
// use the system target
- TARGETING::targetService().getTopLevelTarget(iv_target);
+ TARGETING::targetService().getTopLevelTarget(i_targ);
// die if there is no system target
- assert(iv_target);
+ assert(i_targ);
}
TARGETING::AttributeTraits<TARGETING::ATTR_IPMI_SENSORS>::Type
l_sensors;
- if( iv_target->tryGetAttr<TARGETING::ATTR_IPMI_SENSORS>(l_sensors) )
+ if( i_targ->tryGetAttr<TARGETING::ATTR_IPMI_SENSORS>(l_sensors) )
{
// get the number of rows by dividing the total size by the size of
@@ -437,27 +509,27 @@ namespace SENSOR
uint16_t (*end)[2] = &l_sensors[array_rows];
uint16_t (*ptr)[2] =
- std::lower_bound(begin, end, iv_name, &compare_it);
+ std::lower_bound(begin, end, i_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)[TARGETING::IPMI_SENSOR_ARRAY_NAME_OFFSET] == iv_name ) )
+ ( (*ptr)[TARGETING::IPMI_SENSOR_ARRAY_NAME_OFFSET] == i_name ) )
{
// found it
l_sensor_number =
(*ptr)[TARGETING::IPMI_SENSOR_ARRAY_NUMBER_OFFSET];
TRACFCOMP(g_trac_ipmi,"Found sensor number %d for HUID=0x%x",
- l_sensor_number, TARGETING::get_huid(iv_target));
+ l_sensor_number, TARGETING::get_huid(i_targ));
}
}
else
{
// bug here...
assert(0,"no IPMI_SENSOR attribute check target HUID=0x%x",
- TARGETING::get_huid(iv_target));
+ TARGETING::get_huid(i_targ));
}
return l_sensor_number;
@@ -512,18 +584,41 @@ namespace SENSOR
//
// setRebootCount - send a new value for the reboot count to the BMC.
//
- errlHndl_t RebootCountSensor::setRebootCount( rebootCount_t i_count )
+ errlHndl_t RebootCountSensor::setRebootCount( uint16_t i_count )
{
- // put the reboot count into the sensor
- // reading byte of the message
- iv_msg->iv_sensor_reading = i_count;
+ // the Reboot_count sensor is defined as a discrete sensor
+ // but the assertion bytes are being used to transfer the count
+ // to the bmc, will need to byte swap the data
+ iv_msg->iv_assertion_mask = le16toh(i_count);
return writeSensorData();
}
//
+ // getRebootCount - get the reboot count from the BMC
+ //
+ errlHndl_t RebootCountSensor::getRebootCount( uint16_t &o_rebootCount )
+ {
+
+ // the Reboot_count sensor is defined as a discrete sensor
+ // but the assertion bytes are being used to transfer the count
+ // from the BMC
+ getSensorReadingData l_data;
+
+ errlHndl_t l_err = readSensorData( l_data );
+
+ if( l_err == NULL )
+ {
+ // this value is already byteswapped
+ o_rebootCount = l_data.event_status;
+ }
+ return l_err;
+
+ }
+
+ //
// StatusSensor constructor - uses system DIMM/CORE/PROC target
//
StatusSensor::StatusSensor( TARGETING::Target * i_target )
@@ -702,10 +797,8 @@ namespace SENSOR
//
//
OCCActiveSensor::OCCActiveSensor( TARGETING::Target * i_pTarget )
- :SensorBase(TARGETING::SENSOR_NAME_OCC_ACTIVE, i_pTarget ),
- iv_functionalOffset(PROC_DISABLED)
+ :SensorBase(TARGETING::SENSOR_NAME_OCC_ACTIVE, i_pTarget )
{
-
};
//
@@ -718,36 +811,50 @@ namespace SENSOR
// send the message to the BMC to update the event status for this sensor.
errlHndl_t OCCActiveSensor::setState( OccStateEnum i_state )
{
-
errlHndl_t l_err = NULL;
- uint16_t func_mask = setMask( iv_functionalOffset );
+ // assert the specified state
+ iv_msg->iv_assertion_mask = setMask(i_state);
- switch ( i_state )
- {
+ l_err = writeSensorData();
- case OCC_ACTIVE:
- // turn off the disabled bit
- iv_msg->iv_deassertion_mask = func_mask;
- break;
+ return l_err;
- case OCC_NOT_ACTIVE:
- // assert the disabled bit
- iv_msg->iv_assertion_mask = func_mask;
- break;
+ };
- default:
- // assert that it is non-functional
- iv_msg->iv_assertion_mask = func_mask;
- break;
- }
+ // send the message to the BMC to read the event status for this sensor,
+ // will return true if the "disabled" state of the sensor is not
+ // asserted
+ bool OCCActiveSensor::isActive( )
+ {
+ getSensorReadingData l_data;
- l_err = writeSensorData();
+ bool is_active = false;
+ // set the mask, but dont swap the bytes since we are using it locally
+ // not passing it in the set sensor cmd
+ uint16_t mask = setMask( OCC_ACTIVE, false );
- return l_err;
+ errlHndl_t l_err = readSensorData( l_data );
+
+ if( l_err == NULL )
+ {
+ // check if "disabled" offset has been asserted -
+ // this would indicate that the OCC was not yet enabled
+ if( l_data.event_status & mask )
+ {
+ is_active = true;
+ }
+ }
+ else
+ {
+ // commit the error and return "not active" by default
+ errlCommit( l_err, IPMI_COMP_ID );
+ }
+
+ return is_active;
+ }
- };
//
// HostStausSensor constructor - uses system target
@@ -845,9 +952,9 @@ namespace SENSOR
{
errlCommit( l_err, IPMI_COMP_ID );
}
- }
+ }
- }
+ }
void updateBMCFaultSensorStatus(void)
{
OpenPOWER on IntegriCloud