From b9d86f4c791823c8bc0387578effcf2ef88c0231 Mon Sep 17 00:00:00 2001 From: Tom Joseph Date: Wed, 26 Jul 2017 18:03:47 +0530 Subject: dcmi: Refactor get power limit command Change-Id: I31755eaccb17c013fd2c1a3e43e7ec95a1947ba3 Signed-off-by: Tom Joseph --- dcmihandler.cpp | 122 ++++++++++++++++++++++++++++++++------------------------ dcmihandler.hpp | 45 ++++++++++++++++++++- 2 files changed, 114 insertions(+), 53 deletions(-) diff --git a/dcmihandler.cpp b/dcmihandler.cpp index 9205207..2e0204d 100644 --- a/dcmihandler.cpp +++ b/dcmihandler.cpp @@ -23,6 +23,9 @@ constexpr auto POWER_CAP_ENABLE_PROP = "PowerCapEnable"; using namespace phosphor::logging; +namespace dcmi +{ + uint32_t getPcap(sdbusplus::bus::bus& bus) { auto settingService = ipmi::getService(bus, @@ -39,14 +42,12 @@ uint32_t getPcap(sdbusplus::bus::bus& bus) 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; + elog(); } sdbusplus::message::variant pcap; reply.read(pcap); - return sdbusplus::message::variant_ns::get(pcap); + return pcap.get(); } bool getPcapEnabled(sdbusplus::bus::bus& bus) @@ -65,58 +66,14 @@ bool getPcapEnabled(sdbusplus::bus::bus& bus) 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; + elog(); } sdbusplus::message::variant pcapEnabled; reply.read(pcapEnabled); - return sdbusplus::message::variant_ns::get(pcapEnabled); + return pcapEnabled.get(); } -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; - - // 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}; - - - 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); - - return rc; -} - -namespace dcmi -{ - void readAssetTagObjectTree(dcmi::assettag::ObjectTree& objectTree) { static constexpr auto mapperBusName = "xyz.openbmc_project.ObjectMapper"; @@ -210,6 +167,67 @@ void writeAssetTag(const std::string& assetTag) } // namespace dcmi +ipmi_ret_t getPowerLimit(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) +{ + auto requestData = reinterpret_cast + (request); + std::vector outPayload(sizeof(dcmi::GetPowerLimitResponse)); + auto responseData = reinterpret_cast + (outPayload.data()); + + if (requestData->groupID != dcmi::groupExtId) + { + *data_len = 0; + return IPMI_CC_INVALID_FIELD_REQUEST; + } + + sdbusplus::bus::bus sdbus {ipmid_get_sd_bus_connection()}; + uint32_t pcapValue = 0; + bool pcapEnable = false; + + try + { + pcapValue = dcmi::getPcap(sdbus); + pcapEnable = dcmi::getPcapEnabled(sdbus); + } + catch (InternalFailure& e) + { + *data_len = 0; + return IPMI_CC_UNSPECIFIED_ERROR; + } + + responseData->groupID = dcmi::groupExtId; + + /* + * Exception action if power limit is exceeded and cannot be controlled + * with the correction time limit is hardcoded to Hard Power Off system + * and log event to SEL. + */ + constexpr auto exception = 0x01; + responseData->exceptionAction = exception; + + responseData->powerLimit = static_cast(pcapValue); + + /* + * Correction time limit and Statistics sampling period is currently not + * populated. + */ + + *data_len = outPayload.size(); + memcpy(response, outPayload.data(), *data_len); + + if (pcapEnable) + { + return IPMI_CC_OK; + } + else + { + return IPMI_DCMI_CC_NO_ACTIVE_POWER_LIMIT; + } +} + ipmi_ret_t getAssetTag(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) @@ -348,8 +366,8 @@ ipmi_ret_t setAssetTag(ipmi_netfn_t netfn, ipmi_cmd_t cmd, void register_netfn_dcmi_functions() { // - printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_GRPEXT, IPMI_CMD_DCMI_GET_POWER); - ipmi_register_callback(NETFUN_GRPEXT, IPMI_CMD_DCMI_GET_POWER, NULL, ipmi_dcmi_get_power_limit, + printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_GRPEXT, IPMI_CMD_DCMI_GET_POWER_LIMIT); + ipmi_register_callback(NETFUN_GRPEXT, IPMI_CMD_DCMI_GET_POWER_LIMIT, NULL, getPowerLimit, PRIVILEGE_USER); // diff --git a/dcmihandler.hpp b/dcmihandler.hpp index de0d82f..8ebc660 100644 --- a/dcmihandler.hpp +++ b/dcmihandler.hpp @@ -4,12 +4,13 @@ #include #include #include +#include // IPMI commands for net functions. enum ipmi_netfn_sen_cmds { // Get capability bits - IPMI_CMD_DCMI_GET_POWER = 0x03, + IPMI_CMD_DCMI_GET_POWER_LIMIT = 0x03, IPMI_CMD_DCMI_GET_ASSET_TAG = 0x06, IPMI_CMD_DCMI_SET_ASSET_TAG = 0x08, }; @@ -102,6 +103,48 @@ std::string readAssetTag(); */ void writeAssetTag(const std::string& assetTag); +/** @brief Read the current power cap value + * + * @param[in] bus - dbus connection + * + * @return On success return the power cap value. + */ +uint32_t getPcap(sdbusplus::bus::bus& bus); + +/** @brief Check if the power capping is enabled + * + * @param[in] bus - dbus connection + * + * @return true if the powerCap is enabled and false if the powercap + * is disabled. + */ +bool getPcapEnabled(sdbusplus::bus::bus& bus); + +/** @struct GetPowerLimitRequest + * + * DCMI payload for Get Power Limit command request. + */ +struct GetPowerLimitRequest +{ + uint8_t groupID; //!< Group extension identification. + uint16_t reserved; //!< Reserved +} __attribute__((packed)); + +/** @struct GetPowerLimitResponse + * + * DCMI payload for Get Power Limit command response. + */ +struct GetPowerLimitResponse +{ + uint8_t groupID; //!< Group extension identification. + uint16_t reserved; //!< Reserved. + uint8_t exceptionAction; //!< Exception action. + uint16_t powerLimit; //!< Power limit requested in watts. + uint32_t correctionTime; //!< Correction time limit in milliseconds. + uint16_t reserved1; //!< Reserved. + uint16_t samplingPeriod; //!< Statistics sampling period in seconds. +} __attribute__((packed)); + } // namespace dcmi #endif -- cgit v1.2.1