Use Idle Power Saver parameters from DBus
Allows users to enable and update the IPS parameters instead of
using hardcoded values.
Change-Id: I9010c4b4d3dbdf130a4a778f71c87279681a9f1a
Signed-off-by: Chris Cain <cjcain@us.ibm.com>
diff --git a/occ_status.cpp b/occ_status.cpp
index ab6b9d1..b1893fd 100644
--- a/occ_status.cpp
+++ b/occ_status.cpp
@@ -172,11 +172,6 @@
fs::path(DEV_PATH) /
fs::path(sysfsName + "." + std::to_string(instance + 1)) / "occ_state";
- log<level::DEBUG>(
- fmt::format("Status::readOccState: reading OCC{} state from {}",
- instance, filename.c_str())
- .c_str());
-
std::ifstream file(filename, std::ios::in);
const int open_errno = errno;
if (file)
@@ -272,6 +267,124 @@
return pmode;
}
+// Get the requested power mode
+bool Status::getIPSParms(uint8_t& enterUtil, uint16_t& enterTime,
+ uint8_t& exitUtil, uint16_t& exitTime)
+{
+ using namespace open_power::occ::powermode;
+ // Defaults:
+ bool ipsEnabled = false; // Disabled
+ enterUtil = 8; // Enter Utilization (8%)
+ enterTime = 240; // Enter Delay Time (240s)
+ exitUtil = 12; // Exit Utilization (12%)
+ exitTime = 10; // Exit Delay Time (10s)
+
+ std::map<std::string, std::variant<bool, uint8_t, uint64_t>>
+ ipsProperties{};
+
+ // Get all IPS properties from DBus
+ try
+ {
+ auto& bus = utils::getBus();
+ auto service = utils::getService(PIPS_PATH, PIPS_INTERFACE);
+ auto method =
+ bus.new_method_call(service.c_str(), PIPS_PATH,
+ "org.freedesktop.DBus.Properties", "GetAll");
+ method.append(PIPS_INTERFACE);
+ auto reply = bus.call(method);
+ reply.read(ipsProperties);
+ }
+ catch (const sdbusplus::exception::exception& e)
+ {
+ log<level::ERR>(
+ fmt::format(
+ "Unable to read Idle Power Saver parameters so it will be disabled: {}",
+ e.what())
+ .c_str());
+ return ipsEnabled;
+ }
+
+ auto ipsEntry = ipsProperties.find(IPS_ENABLED_PROP);
+ if (ipsEntry != ipsProperties.end())
+ {
+ ipsEnabled = std::get<bool>(ipsEntry->second);
+ }
+ else
+ {
+ log<level::ERR>(
+ fmt::format("Status::getIPSParms could not find property: {}",
+ IPS_ENABLED_PROP)
+ .c_str());
+ }
+
+ ipsEntry = ipsProperties.find(IPS_ENTER_UTIL);
+ if (ipsEntry != ipsProperties.end())
+ {
+ enterUtil = std::get<uint8_t>(ipsEntry->second);
+ }
+ else
+ {
+ log<level::ERR>(
+ fmt::format("Status::getIPSParms could not find property: {}",
+ IPS_ENTER_UTIL)
+ .c_str());
+ }
+
+ ipsEntry = ipsProperties.find(IPS_ENTER_TIME);
+ if (ipsEntry != ipsProperties.end())
+ {
+ std::chrono::milliseconds ms(std::get<uint64_t>(ipsEntry->second));
+ enterTime =
+ std::chrono::duration_cast<std::chrono::seconds>(ms).count();
+ }
+ else
+ {
+ log<level::ERR>(
+ fmt::format("Status::getIPSParms could not find property: {}",
+ IPS_ENTER_TIME)
+ .c_str());
+ }
+
+ ipsEntry = ipsProperties.find(IPS_EXIT_UTIL);
+ if (ipsEntry != ipsProperties.end())
+ {
+ exitUtil = std::get<uint8_t>(ipsEntry->second);
+ }
+ else
+ {
+ log<level::ERR>(
+ fmt::format("Status::getIPSParms could not find property: {}",
+ IPS_EXIT_UTIL)
+ .c_str());
+ }
+
+ ipsEntry = ipsProperties.find(IPS_EXIT_TIME);
+ if (ipsEntry != ipsProperties.end())
+ {
+ std::chrono::milliseconds ms(std::get<uint64_t>(ipsEntry->second));
+ exitTime = std::chrono::duration_cast<std::chrono::seconds>(ms).count();
+ }
+ else
+ {
+ log<level::ERR>(
+ fmt::format("Status::getIPSParms could not find property: {}",
+ IPS_EXIT_TIME)
+ .c_str());
+ }
+
+ if (enterUtil > exitUtil)
+ {
+ log<level::ERR>(
+ fmt::format(
+ "ERROR: Idle Power Saver Enter Utilization ({}%) is > Exit Utilization ({}%) - using Exit for both",
+ enterUtil, exitUtil)
+ .c_str());
+ enterUtil = exitUtil;
+ }
+
+ return ipsEnabled;
+}
+
// Special processing that needs to happen once the OCCs change to ACTIVE state
void Status::occsWentActive()
{
@@ -325,6 +438,7 @@
if (VALID_POWER_MODE_SETTING(newMode))
{
std::vector<std::uint8_t> cmd, rsp;
+ cmd.reserve(9);
cmd.push_back(uint8_t(CmdType::SET_MODE_AND_STATE));
cmd.push_back(0x00); // Data Length (2 bytes)
cmd.push_back(0x06);
@@ -344,18 +458,15 @@
{
if (rsp.size() == 5)
{
- if (RspStatus::SUCCESS == RspStatus(rsp[2]))
- {
- log<level::DEBUG>(
- "Status::sendModeChange: - Mode change completed successfully");
- }
- else
+ if (RspStatus::SUCCESS != RspStatus(rsp[2]))
{
log<level::ERR>(
fmt::format(
"Status::sendModeChange: SET MODE failed with status 0x{:02X}",
rsp[2])
.c_str());
+ dump_hex(rsp);
+ status = CmdStatus::FAILURE;
}
}
else
@@ -363,14 +474,15 @@
log<level::ERR>(
"Status::sendModeChange: INVALID SET MODE response");
dump_hex(rsp);
+ status = CmdStatus::FAILURE;
}
}
else
{
if (status == CmdStatus::OPEN_FAILURE)
{
- log<level::WARNING>(
- "Status::sendModeChange: OCC not active yet");
+ log<level::INFO>("Status::sendModeChange: OCC not active yet");
+ status = CmdStatus::SUCCESS;
}
else
{
@@ -385,6 +497,7 @@
"Status::sendModeChange: Unable to set power mode to {}",
newMode)
.c_str());
+ status = CmdStatus::FAILURE;
}
return status;
@@ -412,42 +525,49 @@
return CmdStatus::SUCCESS;
}
- std::vector<std::uint8_t> cmd, rsp;
- cmd.push_back(uint8_t(CmdType::SET_CONFIG_DATA));
- cmd.push_back(0x00); // Data Length (2 bytes)
- cmd.push_back(0x09);
- // Data:
- cmd.push_back(0x11); // Config Format: IPS Settings
- cmd.push_back(0x00); // Version
- cmd.push_back(0x00); // IPS Enable: disabled
- cmd.push_back(0x00); // Enter Delay Time (240s)
- cmd.push_back(0xF0); //
- cmd.push_back(0x08); // Enter Utilization (8%)
- cmd.push_back(0x00); // Exit Delay Time (10s)
- cmd.push_back(0x0A); //
- cmd.push_back(0x0C); // Exit Utilization (12%)
+ uint8_t enterUtil, exitUtil;
+ uint16_t enterTime, exitTime;
+ const bool ipsEnabled =
+ getIPSParms(enterUtil, enterTime, exitUtil, exitTime);
+
log<level::INFO>(
fmt::format(
- "Status::sendIpsData: SET_CFG_DATA[IPS] command to OCC{} ({} bytes)",
- instance, cmd.size())
+ "Idle Power Saver Parameters: enabled:{}, enter:{}%/{}s, exit:{}%/{}s",
+ ipsEnabled, enterUtil, enterTime, exitUtil, exitTime)
.c_str());
+
+ std::vector<std::uint8_t> cmd, rsp;
+ cmd.reserve(12);
+ cmd.push_back(uint8_t(CmdType::SET_CONFIG_DATA));
+ cmd.push_back(0x00); // Data Length (2 bytes)
+ cmd.push_back(0x09); //
+ cmd.push_back(0x11); // Config Format: IPS Settings
+ cmd.push_back(0x00); // Version
+ cmd.push_back(ipsEnabled ? 1 : 0); // IPS Enable
+ cmd.push_back(enterTime >> 8); // Enter Delay Time
+ cmd.push_back(enterTime & 0xFF); //
+ cmd.push_back(enterUtil); // Enter Utilization
+ cmd.push_back(exitTime >> 8); // Exit Delay Time
+ cmd.push_back(exitTime & 0xFF); //
+ cmd.push_back(exitUtil); // Exit Utilization
+ log<level::INFO>(fmt::format("Status::sendIpsData: SET_CFG_DATA[IPS] "
+ "command to OCC{} ({} bytes)",
+ instance, cmd.size())
+ .c_str());
status = occCmd.send(cmd, rsp);
if (status == CmdStatus::SUCCESS)
{
if (rsp.size() == 5)
{
- if (RspStatus::SUCCESS == RspStatus(rsp[2]))
- {
- log<level::DEBUG>(
- "Status::sendIpsData: - SET_CFG_DATA[IPS] completed successfully");
- }
- else
+ if (RspStatus::SUCCESS != RspStatus(rsp[2]))
{
log<level::ERR>(
fmt::format(
"Status::sendIpsData: SET_CFG_DATA[IPS] failed with status 0x{:02X}",
rsp[2])
.c_str());
+ dump_hex(rsp);
+ status = CmdStatus::FAILURE;
}
}
else
@@ -455,13 +575,15 @@
log<level::ERR>(
"Status::sendIpsData: INVALID SET_CFG_DATA[IPS] response");
dump_hex(rsp);
+ status = CmdStatus::FAILURE;
}
}
else
{
if (status == CmdStatus::OPEN_FAILURE)
{
- log<level::WARNING>("Status::sendIpsData: OCC not active yet");
+ log<level::INFO>("Status::sendIpsData: OCC not active yet");
+ status = CmdStatus::SUCCESS;
}
else
{