dcmi: Refactor get power limit command
Change-Id: I31755eaccb17c013fd2c1a3e43e7ec95a1947ba3
Signed-off-by: Tom Joseph <tomjoseph@in.ibm.com>
diff --git a/dcmihandler.cpp b/dcmihandler.cpp
index 9205207..2e0204d 100644
--- a/dcmihandler.cpp
+++ b/dcmihandler.cpp
@@ -23,6 +23,9 @@
using namespace phosphor::logging;
+namespace dcmi
+{
+
uint32_t getPcap(sdbusplus::bus::bus& bus)
{
auto settingService = ipmi::getService(bus,
@@ -39,14 +42,12 @@
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 @@
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 @@
} // 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 @@
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 @@
*/
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