diff options
author | Marri Devender Rao <devenrao@in.ibm.com> | 2018-01-18 10:48:37 -0600 |
---|---|---|
committer | Tom Joseph <tomjoseph@in.ibm.com> | 2018-02-06 05:21:43 +0000 |
commit | 66c5fda293759e993c18812cac4620a210387dba (patch) | |
tree | ce371fe2e4c24679e3a7e0abdfc303fea4ad28c7 | |
parent | 138e01889a4fb60c80de9b67048a959e8e671516 (diff) | |
download | phosphor-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.ac | 5 | ||||
-rw-r--r-- | dcmihandler.cpp | 71 | ||||
-rw-r--r-- | dcmihandler.hpp | 42 |
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 |