From 50c0c8fb869a398ddef0f871fb9ea9ba298218c0 Mon Sep 17 00:00:00 2001 From: Andrew Geissler Date: Tue, 11 Jul 2017 16:18:51 -0500 Subject: dcmi: get real power cap settings Now that the user power cap settings are defined, provide them via the ipmi dcmi interface Change-Id: I46b0c3f006eee714c7f412f2aec4433e67aeb187 Signed-off-by: Andrew Geissler --- dcmihandler.cpp | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 86 insertions(+), 8 deletions(-) (limited to 'dcmihandler.cpp') diff --git a/dcmihandler.cpp b/dcmihandler.cpp index 4c4f8b7..43c27f8 100644 --- a/dcmihandler.cpp +++ b/dcmihandler.cpp @@ -1,10 +1,12 @@ #include "dcmihandler.hpp" #include "host-ipmid/ipmid-api.h" #include +#include +#include +#include "utils.hpp" #include #include #include -#include "utils.hpp" #include "xyz/openbmc_project/Common/error.hpp" using namespace phosphor::logging; @@ -13,23 +15,99 @@ using InternalFailure = void register_netfn_dcmi_functions() __attribute__((constructor)); +constexpr auto PCAP_SETTINGS_SERVICE = "xyz.openbmc_project.Settings"; +constexpr auto PCAP_PATH = "/xyz/openbmc_project/control/host0/power_cap"; +constexpr auto PCAP_INTERFACE = "xyz.openbmc_project.Control.Power.Cap"; + +constexpr auto POWER_CAP_PROP = "PowerCap"; +constexpr auto POWER_CAP_ENABLE_PROP = "PowerCapEnable"; + +using namespace phosphor::logging; + +uint32_t getPcap(sdbusplus::bus::bus& bus) +{ + auto settingService = ipmi::getService(bus, + PCAP_PATH,PCAP_SETTINGS_SERVICE); + + auto method = bus.new_method_call(settingService.c_str(), + PCAP_PATH, + "org.freedesktop.DBus.Properties", + "Get"); + + method.append(PCAP_INTERFACE, POWER_CAP_PROP); + auto reply = bus.call(method); + + if (reply.is_method_error()) + { + log("Error in getPcap prop"); + // TODO openbmc/openbmc#851 - Once available, throw returned error + // and return IPMI_CC_UNSPECIFIED_ERROR to caller + return 0; + } + sdbusplus::message::variant pcap; + reply.read(pcap); + + return sdbusplus::message::variant_ns::get(pcap); +} + +bool getPcapEnabled(sdbusplus::bus::bus& bus) +{ + auto settingService = ipmi::getService(bus, + PCAP_PATH,PCAP_SETTINGS_SERVICE); + + auto method = bus.new_method_call(settingService.c_str(), + PCAP_PATH, + "org.freedesktop.DBus.Properties", + "Get"); + + method.append(PCAP_INTERFACE, POWER_CAP_ENABLE_PROP); + auto reply = bus.call(method); + + if (reply.is_method_error()) + { + log("Error in getPcapEnabled prop"); + // TODO openbmc/openbmc#851 - Once available, throw returned error + // and return IPMI_CC_UNSPECIFIED_ERROR to caller + return false; + } + sdbusplus::message::variant pcapEnabled; + reply.read(pcapEnabled); + + return sdbusplus::message::variant_ns::get(pcapEnabled); +} ipmi_ret_t ipmi_dcmi_get_power_limit(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) { + // Default to no power cap enabled ipmi_ret_t rc = IPMI_DCMI_CC_NO_ACTIVE_POWER_LIMIT; - // dcmi-v1-5-rev-spec.pdf 6.6.2. - // This is good enough for OpenBMC support for OpenPOWER based systems - // TODO research if more is needed - uint8_t data_response[] = { 0xDC, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01}; + // Get our sdbus object + sd_bus *bus = ipmid_get_sd_bus_connection(); + sdbusplus::bus::bus sdbus {bus}; + + // Read our power cap settings + auto pcap = getPcap(sdbus); + auto pcapEnable = getPcapEnabled(sdbus); + if(pcapEnable) + { + // indicate power cap enabled with success return code + rc = IPMI_CC_OK; + } + uint8_t pcapBytes[2] = {0}; + pcapBytes[1] = (pcap & 0xFF00) >> 8; + pcapBytes[0] = pcap & 0xFF; + // dcmi-v1-5-rev-spec.pdf 6.6.2. + uint8_t data_response[] = { 0xDC, 0x00, 0x00, 0x01, pcapBytes[0], + pcapBytes[1], 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01}; - printf("IPMI DCMI_GET_POWER_LEVEL\n"); + log("IPMI DCMI POWER CAP INFO", + entry("DCMI_PCAP=%u",pcap), + entry("DCMI_PCAP_ENABLE=%u",pcapEnable)); memcpy(response, data_response, sizeof(data_response)); *data_len = sizeof(data_response); -- cgit v1.2.1