summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarri Devender Rao <devenrao@in.ibm.com>2018-01-18 10:48:37 -0600
committerTom Joseph <tomjoseph@in.ibm.com>2018-02-06 05:21:43 +0000
commit66c5fda293759e993c18812cac4620a210387dba (patch)
treece371fe2e4c24679e3a7e0abdfc303fea4ad28c7
parent138e01889a4fb60c80de9b67048a959e8e671516 (diff)
downloadphosphor-host-ipmid-66c5fda293759e993c18812cac4620a210387dba.tar.gz
phosphor-host-ipmid-66c5fda293759e993c18812cac4620a210387dba.zip
DCMI: Read power value from the configured D-Bus object path
1) Parse the power_reading JSON configuration file to get the D-Bus object path for the power reading. 2) Read the power reading value from the specified D-Bus object. Change-Id: I4b9f0703318e8db2c86d0b337e524eee6da33d08 Signed-off-by: Marri Devender Rao <devenrao@in.ibm.com>
-rw-r--r--configure.ac5
-rw-r--r--dcmihandler.cpp71
-rw-r--r--dcmihandler.hpp42
3 files changed, 118 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac
index 0e124a3..ac42e1d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -152,6 +152,11 @@ AS_IF([test "x$CONTROL_HOST_OBJ_MGR" == "x"],
[CONTROL_HOST_OBJ_MGR="/xyz/openbmc_project/control"])
AC_DEFINE_UNQUOTED([CONTROL_HOST_OBJ_MGR], ["$CONTROL_HOST_OBJ_MGR"], [The Control Host D-Bus Object Manager])
+# Power reading sensor configuration file
+AC_ARG_VAR(POWER_READING_SENSOR, [Power reading sensor configuration file])
+AS_IF([test "x$POWER_READING_SENSOR" == "x"],[POWER_READING_SENSOR="/usr/share/ipmi-providers/power_reading.json"])
+AC_DEFINE_UNQUOTED([POWER_READING_SENSOR], ["$POWER_READING_SENSOR"], [Power reading sensor configuration file])
+
# Create configured output
AC_CONFIG_FILES([Makefile test/Makefile softoff/Makefile softoff/test/Makefile])
AC_OUTPUT
diff --git a/dcmihandler.cpp b/dcmihandler.cpp
index 8b47845..3c77ed5 100644
--- a/dcmihandler.cpp
+++ b/dcmihandler.cpp
@@ -3,6 +3,7 @@
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/log.hpp>
#include <sdbusplus/bus.hpp>
+#include <nlohmann/json.hpp>
#include "utils.hpp"
#include <stdio.h>
#include <string.h>
@@ -11,6 +12,7 @@
#include <bitset>
#include <cmath>
#include "xyz/openbmc_project/Common/error.hpp"
+#include "config.h"
using namespace phosphor::logging;
using InternalFailure =
@@ -29,6 +31,10 @@ constexpr auto DCMI_SPEC_MAJOR_VERSION = 1;
constexpr auto DCMI_SPEC_MINOR_VERSION = 5;
constexpr auto DCMI_CAP_JSON_FILE = "/usr/share/ipmi-providers/dcmi_cap.json";
+constexpr auto SENSOR_VALUE_INTF = "xyz.openbmc_project.Sensor.Value";
+constexpr auto SENSOR_VALUE_PROP = "Value";
+constexpr auto SENSOR_SCALE_PROP = "Scale";
+
using namespace phosphor::logging;
namespace dcmi
@@ -1004,6 +1010,68 @@ ipmi_ret_t getTempReadings(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
return IPMI_CC_OK;
}
+int64_t getPowerReading(sdbusplus::bus::bus& bus)
+{
+ std::ifstream sensorFile(POWER_READING_SENSOR);
+ std::string objectPath;
+ if (!sensorFile.is_open())
+ {
+ log<level::ERR>("Power reading configuration file not found",
+ entry("POWER_SENSOR_FILE=%s", POWER_READING_SENSOR));
+ elog<InternalFailure>();
+ }
+
+ auto data = nlohmann::json::parse(sensorFile, nullptr, false);
+ if (data.is_discarded())
+ {
+ log<level::ERR>("Error in parsing configuration file",
+ entry("POWER_SENSOR_FILE=%s", POWER_READING_SENSOR));
+ elog<InternalFailure>();
+ }
+
+ objectPath = data.value("path", "");
+ if (objectPath.empty())
+ {
+ log<level::ERR>("Power sensor D-Bus object path is empty",
+ entry("POWER_SENSOR_FILE=%s", POWER_READING_SENSOR));
+ elog<InternalFailure>();
+ }
+
+ auto service = ipmi::getService(bus, SENSOR_VALUE_INTF, objectPath);
+
+ //Read the sensor value and scale properties
+ auto properties = ipmi::getAllDbusProperties(
+ bus, service, objectPath, SENSOR_VALUE_INTF);
+ auto power = properties[SENSOR_VALUE_PROP].get<int64_t>();
+ auto scale = properties[SENSOR_SCALE_PROP].get<int64_t>();
+
+ // Power reading needs to be scaled with the Scale value using the formula
+ // Value * 10^Scale.
+ power *= std::pow(10, scale);
+
+ return power;
+}
+
+ipmi_ret_t getPowerReading(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_request_t request, ipmi_response_t response,
+ ipmi_data_len_t data_len, ipmi_context_t context)
+{
+ ipmi_ret_t rc = IPMI_CC_OK;
+ sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
+ try
+ {
+ getPowerReading(bus);
+ }
+ catch (InternalFailure& e)
+ {
+ log<level::ERR>("Error in reading power sensor value",
+ entry("INTERFACE=%s", SENSOR_VALUE_INTF),
+ entry("PROPERTY=%s", SENSOR_VALUE_PROP));
+ return IPMI_CC_UNSPECIFIED_ERROR;
+ }
+ return rc;
+}
+
void register_netfn_dcmi_functions()
{
// <Get Power Limit>
@@ -1062,6 +1130,9 @@ void register_netfn_dcmi_functions()
ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_TEMP_READINGS,
NULL, getTempReadings, PRIVILEGE_USER);
+ // <Get Power Reading>
+ ipmi_register_callback(NETFUN_GRPEXT, dcmi::Commands::GET_POWER_READING,
+ NULL, getPowerReading, PRIVILEGE_USER);
return;
}
// 956379
diff --git a/dcmihandler.hpp b/dcmihandler.hpp
index bd2c6e1..4e95eba 100644
--- a/dcmihandler.hpp
+++ b/dcmihandler.hpp
@@ -14,6 +14,7 @@ enum Commands
{
// Get capability bits
GET_CAPABILITIES = 0x01,
+ GET_POWER_READING = 0x02,
GET_POWER_LIMIT = 0x03,
SET_POWER_LIMIT = 0x04,
APPLY_POWER_LIMIT = 0x05,
@@ -427,6 +428,47 @@ namespace temp_readings
uint8_t instanceStart);
}
+/** @brief Read power reading from power reading sensor object
+ *
+ * @param[in] bus - dbus connection
+ *
+ * @return total power reading
+ */
+int64_t getPowerReading(sdbusplus::bus::bus& bus);
+
+/** @struct GetPowerReadingRequest
+ *
+ * DCMI Get Power Reading command request.
+ * Refer DCMI specification Version 1.1 Section 6.6.1
+ */
+struct GetPowerReadingRequest
+{
+ uint8_t groupID; //!< Group extension identification.
+ uint8_t mode; //!< Mode
+ uint8_t modeAttribute; //!< Mode Attributes
+} __attribute__((packed));
+
+/** @struct GetPowerReadingResponse
+ *
+ * DCMI Get Power Reading command response.
+ * Refer DCMI specification Version 1.1 Section 6.6.1
+ */
+struct GetPowerReadingResponse
+{
+ uint8_t groupID; //!< Group extension identification.
+ uint16_t currentPower; //!< Current power in watts
+ uint16_t minimumPower; //!< Minimum power over sampling duration
+ //!< in watts
+ uint16_t maximumPower; //!< Maximum power over sampling duration
+ //!< in watts
+ uint16_t averagePower; //!< Average power over sampling duration
+ //!< in watts
+ uint32_t timeStamp; //!< IPMI specification based time stamp
+ uint32_t timeFrame; //!< Statistics reporting time period in milli
+ //!< seconds.
+ uint8_t powerReadingState; //!< Power Reading State
+} __attribute__((packed));
+
} // namespace dcmi
#endif
OpenPOWER on IntegriCloud