diff options
-rw-r--r-- | dcmihandler.cpp | 65 | ||||
-rw-r--r-- | dcmihandler.hpp | 33 |
2 files changed, 98 insertions, 0 deletions
diff --git a/dcmihandler.cpp b/dcmihandler.cpp index 2e0204d..11a3730 100644 --- a/dcmihandler.cpp +++ b/dcmihandler.cpp @@ -74,6 +74,27 @@ bool getPcapEnabled(sdbusplus::bus::bus& bus) return pcapEnabled.get<bool>(); } +void setPcap(sdbusplus::bus::bus& bus, const uint32_t powerCap) +{ + auto service = ipmi::getService(bus, PCAP_INTERFACE, PCAP_PATH); + + auto method = bus.new_method_call(service.c_str(), + PCAP_PATH, + "org.freedesktop.DBus.Properties", + "Set"); + + method.append(PCAP_INTERFACE, POWER_CAP_PROP); + method.append(sdbusplus::message::variant<uint32_t>(powerCap)); + + auto reply = bus.call(method); + + if (reply.is_method_error()) + { + log<level::ERR>("Error in setPcap property"); + elog<InternalFailure>(); + } +} + void readAssetTagObjectTree(dcmi::assettag::ObjectTree& objectTree) { static constexpr auto mapperBusName = "xyz.openbmc_project.ObjectMapper"; @@ -228,6 +249,45 @@ ipmi_ret_t getPowerLimit(ipmi_netfn_t netfn, ipmi_cmd_t cmd, } } +ipmi_ret_t setPowerLimit(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::SetPowerLimitRequest*> + (request); + std::vector<uint8_t> outPayload(sizeof(dcmi::SetPowerLimitResponse)); + auto responseData = reinterpret_cast<dcmi::SetPowerLimitResponse*> + (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()}; + + // Only process the power limit requested in watts. + try + { + dcmi::setPcap(sdbus, requestData->powerLimit); + } + catch (InternalFailure& e) + { + *data_len = 0; + return IPMI_CC_UNSPECIFIED_ERROR; + } + + log<level::INFO>("Set Power Cap", + entry("POWERCAP=%u", requestData->powerLimit)); + + responseData->groupID = dcmi::groupExtId; + memcpy(response, outPayload.data(), outPayload.size()); + *data_len = outPayload.size(); + + return IPMI_CC_OK; +} + 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) @@ -370,6 +430,11 @@ void register_netfn_dcmi_functions() ipmi_register_callback(NETFUN_GRPEXT, IPMI_CMD_DCMI_GET_POWER_LIMIT, NULL, getPowerLimit, PRIVILEGE_USER); + // <Set Power Limit> + printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_GRPEXT, IPMI_CMD_DCMI_SET_POWER_LIMIT); + ipmi_register_callback(NETFUN_GRPEXT, IPMI_CMD_DCMI_SET_POWER_LIMIT, NULL, setPowerLimit, + PRIVILEGE_OPERATOR); + // <Get Asset Tag> printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_GRPEXT, IPMI_CMD_DCMI_GET_ASSET_TAG); ipmi_register_callback(NETFUN_GRPEXT, IPMI_CMD_DCMI_GET_ASSET_TAG, NULL, getAssetTag, diff --git a/dcmihandler.hpp b/dcmihandler.hpp index 8ebc660..e318294 100644 --- a/dcmihandler.hpp +++ b/dcmihandler.hpp @@ -11,6 +11,7 @@ enum ipmi_netfn_sen_cmds { // Get capability bits IPMI_CMD_DCMI_GET_POWER_LIMIT = 0x03, + IPMI_CMD_DCMI_SET_POWER_LIMIT = 0x04, IPMI_CMD_DCMI_GET_ASSET_TAG = 0x06, IPMI_CMD_DCMI_SET_ASSET_TAG = 0x08, }; @@ -145,6 +146,38 @@ struct GetPowerLimitResponse uint16_t samplingPeriod; //!< Statistics sampling period in seconds. } __attribute__((packed)); +/** @brief Set the power cap value + * + * @param[in] bus - dbus connection + * @param[in] powerCap - power cap value + */ +void setPcap(sdbusplus::bus::bus& bus, const uint32_t powerCap); + +/** @struct SetPowerLimitRequest + * + * DCMI payload for Set Power Limit command request. + */ +struct SetPowerLimitRequest +{ + uint8_t groupID; //!< Group extension identification. + uint16_t reserved; //!< Reserved + uint8_t reserved1; //!< Reserved + uint8_t exceptionAction; //!< Exception action. + uint16_t powerLimit; //!< Power limit requested in watts. + uint32_t correctionTime; //!< Correction time limit in milliseconds. + uint16_t reserved2; //!< Reserved. + uint16_t samplingPeriod; //!< Statistics sampling period in seconds. +} __attribute__((packed)); + +/** @struct SetPowerLimitResponse + * + * DCMI payload for Set Power Limit command response. + */ +struct SetPowerLimitResponse +{ + uint8_t groupID; //!< Group extension identification. +} __attribute__((packed)); + } // namespace dcmi #endif |