diff options
author | Tom Joseph <tomjoseph@in.ibm.com> | 2017-07-26 18:03:47 +0530 |
---|---|---|
committer | Patrick Williams <patrick@stwcx.xyz> | 2017-07-28 02:26:09 +0000 |
commit | b9d86f4c791823c8bc0387578effcf2ef88c0231 (patch) | |
tree | d275f6d66daf6a9172991c8cdff58763c80ba9d6 | |
parent | 908f75075bfb4ece993d6dcfb00ceccbe3983f59 (diff) | |
download | phosphor-host-ipmid-b9d86f4c791823c8bc0387578effcf2ef88c0231.tar.gz phosphor-host-ipmid-b9d86f4c791823c8bc0387578effcf2ef88c0231.zip |
dcmi: Refactor get power limit command
Change-Id: I31755eaccb17c013fd2c1a3e43e7ec95a1947ba3
Signed-off-by: Tom Joseph <tomjoseph@in.ibm.com>
-rw-r--r-- | dcmihandler.cpp | 122 | ||||
-rw-r--r-- | 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<level::ERR>("Error in getPcap prop"); - // TODO openbmc/openbmc#851 - Once available, throw returned error - // and return IPMI_CC_UNSPECIFIED_ERROR to caller - return 0; + elog<InternalFailure>(); } sdbusplus::message::variant<uint32_t> pcap; reply.read(pcap); - return sdbusplus::message::variant_ns::get<uint32_t>(pcap); + return pcap.get<uint32_t>(); } bool getPcapEnabled(sdbusplus::bus::bus& bus) @@ -65,58 +66,14 @@ bool getPcapEnabled(sdbusplus::bus::bus& bus) if (reply.is_method_error()) { log<level::ERR>("Error in getPcapEnabled prop"); - // TODO openbmc/openbmc#851 - Once available, throw returned error - // and return IPMI_CC_UNSPECIFIED_ERROR to caller - return false; + elog<InternalFailure>(); } sdbusplus::message::variant<bool> pcapEnabled; reply.read(pcapEnabled); - return sdbusplus::message::variant_ns::get<bool>(pcapEnabled); + return pcapEnabled.get<bool>(); } -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<level::INFO>("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<const dcmi::GetPowerLimitRequest*> + (request); + std::vector<uint8_t> outPayload(sizeof(dcmi::GetPowerLimitResponse)); + auto responseData = reinterpret_cast<dcmi::GetPowerLimitResponse*> + (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<uint16_t>(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() { // <Get Power Limit> - 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); // <Get Asset Tag> diff --git a/dcmihandler.hpp b/dcmihandler.hpp index de0d82f..8ebc660 100644 --- a/dcmihandler.hpp +++ b/dcmihandler.hpp @@ -4,12 +4,13 @@ #include <map> #include <string> #include <vector> +#include <sdbusplus/bus.hpp> // 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 |