Read default power mode & IPS parameters from DBus
If the power mode or idle power saver parameters have never been set,
they will be read from a set of default parameters that are on DBus.
This allows individual systems to have different default settings.
Mode/IPS parameters moved from Settings to OCC.Control
Code verified on Everest hardware with multiple scenarios including
host reboots, BMC reboots, OCC resets.
Change-Id: Id02613455db7f382791ff37c7dc420dbea1e0906
Signed-off-by: Chris Cain <cjcain@us.ibm.com>
diff --git a/powermode.cpp b/powermode.cpp
index 9b9f3cb..fd8679d 100644
--- a/powermode.cpp
+++ b/powermode.cpp
@@ -18,18 +18,38 @@
{
using namespace phosphor::logging;
+using namespace std::literals::string_literals;
+
using Mode = sdbusplus::xyz::openbmc_project::Control::Power::server::Mode;
// Set the Master OCC
-void PowerMode::setMasterOcc(const std::string& occPath)
+void PowerMode::setMasterOcc(const std::string& masterOccPath)
{
- path = occPath;
+ if (masterOccSet)
+ {
+ if (masterOccPath != path)
+ {
+ log<level::ERR>(
+ fmt::format(
+ "PowerMode::setMasterOcc: Master changed (was OCC{}, {})",
+ occInstance, masterOccPath)
+ .c_str());
+ if (occCmd)
+ {
+ occCmd.reset();
+ }
+ }
+ }
+ path = masterOccPath;
occInstance = path.back() - '0';
log<level::DEBUG>(fmt::format("PowerMode::setMasterOcc(OCC{}, {})",
occInstance, path.c_str())
.c_str());
- occCmd = std::make_unique<open_power::occ::OccCommand>(occInstance,
- path.c_str());
+ if (!occCmd)
+ {
+ occCmd = std::make_unique<open_power::occ::OccCommand>(occInstance,
+ path.c_str());
+ }
masterOccSet = true;
};
@@ -48,12 +68,11 @@
SysPwrMode newMode = convertStringToMode(propVal);
if (newMode != SysPwrMode::NO_CHANGE)
{
- // DBus mode changed, get rid of any OEM mode if set
- persistedData.purge();
+ // Update persisted data with new mode
+ persistedData.updateMode(newMode, 0);
log<level::INFO>(
- fmt::format("Power Mode Change Requested: {}", propVal)
- .c_str());
+ fmt::format("DBus Power Mode Changed: {}", propVal).c_str());
// Send mode change to OCC
sendModeChange();
@@ -62,7 +81,7 @@
}
// Called from OCC PassThrough interface (via CE login / BMC command line)
-bool PowerMode::setMode(const SysPwrMode newMode, const uint16_t modeData)
+bool PowerMode::setMode(const SysPwrMode newMode, const uint16_t oemModeData)
{
if (updateDbusMode(newMode) == false)
{
@@ -70,19 +89,14 @@
return false;
}
- // If new mode is valid customer mode, the DBus update will trigger the mode
- // change request to OCC. For OEM modes, the request will be sent here.
- if (VALID_OEM_POWER_MODE_SETTING(newMode))
- {
- // Save OEM mode
- persistedData.writeModeFile(newMode, modeData);
+ // Save mode
+ persistedData.updateMode(newMode, oemModeData);
- // Send mode change to OCC
- if (sendModeChange() != CmdStatus::SUCCESS)
- {
- // Mode change failed
- return false;
- }
+ // Send mode change to OCC
+ if (sendModeChange() != CmdStatus::SUCCESS)
+ {
+ // Mode change failed
+ return false;
}
return true;
@@ -125,7 +139,6 @@
// Check if Hypervisor target is PowerVM
bool isPowerVM()
{
- using namespace open_power::occ::powermode;
namespace Hyper = sdbusplus::com::ibm::Host::server;
constexpr auto HYPE_PATH = "/com/ibm/host0/hypervisor";
constexpr auto HYPE_INTERFACE = "com.ibm.Host.Target";
@@ -156,44 +169,81 @@
return powerVmTarget;
}
-// Get the requested power mode from DBus
-SysPwrMode PowerMode::getDbusMode()
+// Initialize persistent data and return true if successful
+bool PowerMode::initPersistentData()
{
- using namespace open_power::occ::powermode;
- SysPwrMode currentMode;
-
- // This will throw exception on failure
- auto& bus = utils::getBus();
- auto service = utils::getService(PMODE_PATH, PMODE_INTERFACE);
- auto method = bus.new_method_call(service.c_str(), PMODE_PATH,
- "org.freedesktop.DBus.Properties", "Get");
- method.append(PMODE_INTERFACE, POWER_MODE_PROP);
- auto reply = bus.call(method);
-
- std::variant<std::string> stateEntryValue;
- reply.read(stateEntryValue);
- auto propVal = std::get<std::string>(stateEntryValue);
-
- currentMode = powermode::convertStringToMode(propVal);
- if (!VALID_POWER_MODE_SETTING(currentMode))
+ if (!persistedData.modeAvailable())
{
- log<level::ERR>(
- fmt::format(
- "PowerMode::getDbusMode Invalid power mode found on DBus: {}",
- currentMode)
+ // Read the default mode
+ SysPwrMode currentMode;
+ if (!getDefaultMode(currentMode))
+ {
+ // Unable to read defaults
+ return false;
+ }
+ log<level::INFO>(
+ fmt::format("PowerMode::initPersistentData: Using default mode: {}",
+ currentMode)
.c_str());
- currentMode = SysPwrMode::NO_CHANGE;
+
+ // Save default mode as current mode
+ persistedData.updateMode(currentMode, 0);
+
+ // Write default mode to DBus
+ updateDbusMode(currentMode);
}
- return currentMode;
+ if (!persistedData.ipsAvailable())
+ {
+ // Read the default IPS parameters
+ bool ipsEnabled;
+ uint8_t enterUtil, exitUtil;
+ uint16_t enterTime, exitTime;
+ if (!getDefaultIPSParms(ipsEnabled, enterUtil, enterTime, exitUtil,
+ exitTime))
+ {
+ // Unable to read defaults
+ return false;
+ }
+ log<level::INFO>(
+ fmt::format(
+ "PowerMode::initPersistentData: Using default IPS parms: Enabled: {}, EnterUtil: {}%, EnterTime: {}s, ExitUtil: {}%, ExitTime: {}s",
+ ipsEnabled, enterUtil, enterTime, exitUtil, exitTime)
+ .c_str());
+
+ // Save IPS
+ persistedData.updateIPS(ipsEnabled, enterUtil, enterTime, exitUtil,
+ exitTime);
+
+ // Write default IPS data to DBus
+ updateDbusIPS(ipsEnabled, enterUtil, enterTime, exitUtil, exitTime);
+ }
+ return true;
+}
+
+// Get the requested power mode and return true if successful
+bool PowerMode::getMode(SysPwrMode& currentMode, uint16_t& oemModeData)
+{
+ currentMode = SysPwrMode::NO_CHANGE;
+ oemModeData = 0;
+
+ if (!persistedData.getMode(currentMode, oemModeData))
+ {
+ // Persistent data not initialized, read defaults and update DBus
+ if (!initPersistentData())
+ {
+ // Unable to read defaults from entity manager yet
+ return false;
+ }
+ return persistedData.getMode(currentMode, oemModeData);
+ }
+
+ return true;
}
// Set the power mode on DBus
bool PowerMode::updateDbusMode(const SysPwrMode newMode)
{
- using namespace open_power::occ::powermode;
- using namespace std::literals::string_literals;
-
if (!VALID_POWER_MODE_SETTING(newMode) &&
!VALID_OEM_POWER_MODE_SETTING(newMode))
{
@@ -205,25 +255,25 @@
return false;
}
- // Mode::PowerMode dBusMode;
- std::string dBusMode;
+ // Convert mode for DBus
+ ModeInterface::PowerMode dBusMode;
switch (newMode)
{
case SysPwrMode::STATIC:
- dBusMode = PMODE_INTERFACE + ".PowerMode.Static"s;
+ dBusMode = Mode::PowerMode::Static;
break;
case SysPwrMode::POWER_SAVING:
- dBusMode = PMODE_INTERFACE + ".PowerMode.PowerSaving"s;
+ dBusMode = Mode::PowerMode::PowerSaving;
break;
case SysPwrMode::MAX_PERF:
- dBusMode = PMODE_INTERFACE + ".PowerMode.MaximumPerformance"s;
+ dBusMode = Mode::PowerMode::MaximumPerformance;
break;
default:
- dBusMode = PMODE_INTERFACE + ".PowerMode.OEM"s;
+ dBusMode = Mode::PowerMode::OEM;
}
- utils::setProperty(PMODE_PATH, PMODE_INTERFACE, POWER_MODE_PROP,
- std::move(dBusMode));
+ // true = skip update signal
+ ModeInterface::setPropertyByName(POWER_MODE_PROP, dBusMode, true);
return true;
}
@@ -248,14 +298,9 @@
return CmdStatus::SUCCESS;
}
- // Use OEM power mode if it was set
- SysPwrMode newMode = SysPwrMode::NO_CHANGE;
- uint16_t modeData = 0;
- if (persistedData.getOemMode(newMode, modeData) == false)
- {
- // Read customer power mode from Dbus
- newMode = getDbusMode();
- }
+ SysPwrMode newMode;
+ uint16_t oemModeData = 0;
+ getMode(newMode, oemModeData);
if (VALID_POWER_MODE_SETTING(newMode) ||
VALID_OEM_POWER_MODE_SETTING(newMode))
@@ -268,13 +313,13 @@
cmd.push_back(0x30); // Data (Version)
cmd.push_back(uint8_t(OccState::NO_CHANGE));
cmd.push_back(uint8_t(newMode));
- cmd.push_back(modeData >> 8); // Mode Data (Freq Point)
- cmd.push_back(modeData & 0xFF); //
- cmd.push_back(0x00); // reserved
+ cmd.push_back(oemModeData >> 8); // Mode Data (Freq Point)
+ cmd.push_back(oemModeData & 0xFF); //
+ cmd.push_back(0x00); // reserved
log<level::INFO>(
fmt::format(
"PowerMode::sendModeChange: SET_MODE({},{}) command to OCC{} ({} bytes)",
- newMode, modeData, occInstance, cmd.size())
+ newMode, oemModeData, occInstance, cmd.size())
.c_str());
status = occCmd->send(cmd, rsp);
if (status == CmdStatus::SUCCESS)
@@ -340,10 +385,17 @@
ipsProperties{};
msg.read(interface, ipsProperties);
+ // Read persisted values
+ bool ipsEnabled;
+ uint8_t enterUtil, exitUtil;
+ uint16_t enterTime, exitTime;
+ getIPSParms(ipsEnabled, enterUtil, enterTime, exitUtil, exitTime);
+
+ // Check for any changed data
auto ipsEntry = ipsProperties.find(IPS_ENABLED_PROP);
if (ipsEntry != ipsProperties.end())
{
- const auto ipsEnabled = std::get<bool>(ipsEntry->second);
+ ipsEnabled = std::get<bool>(ipsEntry->second);
log<level::INFO>(
fmt::format("Idle Power Saver change: Enabled={}", ipsEnabled)
.c_str());
@@ -352,7 +404,7 @@
ipsEntry = ipsProperties.find(IPS_ENTER_UTIL);
if (ipsEntry != ipsProperties.end())
{
- const auto enterUtil = std::get<uint8_t>(ipsEntry->second);
+ enterUtil = std::get<uint8_t>(ipsEntry->second);
log<level::INFO>(
fmt::format("Idle Power Saver change: Enter Util={}%", enterUtil)
.c_str());
@@ -362,7 +414,7 @@
if (ipsEntry != ipsProperties.end())
{
std::chrono::milliseconds ms(std::get<uint64_t>(ipsEntry->second));
- const auto enterTime =
+ enterTime =
std::chrono::duration_cast<std::chrono::seconds>(ms).count();
log<level::INFO>(
fmt::format("Idle Power Saver change: Enter Time={}sec", enterTime)
@@ -372,7 +424,7 @@
ipsEntry = ipsProperties.find(IPS_EXIT_UTIL);
if (ipsEntry != ipsProperties.end())
{
- const auto exitUtil = std::get<uint8_t>(ipsEntry->second);
+ exitUtil = std::get<uint8_t>(ipsEntry->second);
log<level::INFO>(
fmt::format("Idle Power Saver change: Exit Util={}%", exitUtil)
.c_str());
@@ -382,8 +434,7 @@
if (ipsEntry != ipsProperties.end())
{
std::chrono::milliseconds ms(std::get<uint64_t>(ipsEntry->second));
- const auto exitTime =
- std::chrono::duration_cast<std::chrono::seconds>(ms).count();
+ exitTime = std::chrono::duration_cast<std::chrono::seconds>(ms).count();
log<level::INFO>(
fmt::format("Idle Power Saver change: Exit Time={}sec", exitTime)
.c_str());
@@ -392,118 +443,43 @@
if (parmsChanged)
{
- // Trigger mode change to OCC
+ // Update persistant data with new DBus values
+ persistedData.updateIPS(ipsEnabled, enterUtil, enterTime, exitUtil,
+ exitTime);
+
+ // Trigger IPS data to get sent to the OCC
sendIpsData();
}
return;
}
-/** @brief Get the Idle Power Saver properties
- * @return true if IPS is enabled
+/** @brief Get the Idle Power Saver properties from persisted data
+ * @return true if IPS parameters were read
*/
-bool PowerMode::getIPSParms(uint8_t& enterUtil, uint16_t& enterTime,
- uint8_t& exitUtil, uint16_t& exitTime)
+bool PowerMode::getIPSParms(bool& ipsEnabled, 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)
+ ipsEnabled = true; // Enabled
+ 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{};
+ if (!persistedData.getIPS(ipsEnabled, enterUtil, enterTime, exitUtil,
+ exitTime))
+ {
+ // Persistent data not initialized, read defaults and update DBus
+ if (!initPersistentData())
+ {
+ // Unable to read defaults from entity manager yet
+ return false;
+ }
- // 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("PowerMode::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("PowerMode::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("PowerMode::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("PowerMode::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("PowerMode::getIPSParms could not find property: {}",
- IPS_EXIT_TIME)
- .c_str());
+ persistedData.getIPS(ipsEnabled, enterUtil, enterTime, exitUtil,
+ exitTime);
}
if (enterUtil > exitUtil)
@@ -516,14 +492,30 @@
enterUtil = exitUtil;
}
- return ipsEnabled;
+ return true;
+}
+
+// Set the Idle Power Saver data on DBus
+bool PowerMode::updateDbusIPS(const bool enabled, const uint8_t enterUtil,
+ const uint16_t enterTime, const uint8_t exitUtil,
+ const uint16_t exitTime)
+{
+ // true = skip update signal
+ IpsInterface::setPropertyByName(IPS_ENABLED_PROP, enabled, true);
+ IpsInterface::setPropertyByName(IPS_ENTER_UTIL, enterUtil, true);
+ // Convert time from seconds to ms
+ uint64_t msTime = enterTime * 1000;
+ IpsInterface::setPropertyByName(IPS_ENTER_TIME, msTime, true);
+ IpsInterface::setPropertyByName(IPS_EXIT_UTIL, exitUtil, true);
+ msTime = exitTime * 1000;
+ IpsInterface::setPropertyByName(IPS_EXIT_TIME, msTime, true);
+
+ return true;
}
// Send Idle Power Saver config data to the master OCC
CmdStatus PowerMode::sendIpsData()
{
- CmdStatus status;
-
if (!masterActive || !masterOccSet)
{
// Nothing to do
@@ -538,10 +530,10 @@
return CmdStatus::SUCCESS;
}
+ bool ipsEnabled;
uint8_t enterUtil, exitUtil;
uint16_t enterTime, exitTime;
- const bool ipsEnabled =
- getIPSParms(enterUtil, enterTime, exitUtil, exitTime);
+ getIPSParms(ipsEnabled, enterUtil, enterTime, exitUtil, exitTime);
log<level::INFO>(
fmt::format(
@@ -567,7 +559,7 @@
"command to OCC{} ({} bytes)",
occInstance, cmd.size())
.c_str());
- status = occCmd->send(cmd, rsp);
+ CmdStatus status = occCmd->send(cmd, rsp);
if (status == CmdStatus::SUCCESS)
{
if (rsp.size() == 5)
@@ -608,20 +600,33 @@
return status;
}
-inline void OccPersistData::print()
+void OccPersistData::print()
{
- log<level::DEBUG>(
- fmt::format(
- "OccPersistData: OEM Mode: 0x{:02X}, OEM Mode Freq: {} (0x{:04X})",
- oemData.oemMode, oemData.oemModeFreq, oemData.oemModeFreq)
- .c_str());
+ if (modeData.modeInitialized)
+ {
+ log<level::INFO>(
+ fmt::format(
+ "OccPersistData: Mode: 0x{:02X}, OEM Mode Data: {} (0x{:04X})",
+ modeData.mode, modeData.oemModeData, modeData.oemModeData)
+ .c_str());
+ }
+ if (modeData.ipsInitialized)
+ {
+ log<level::INFO>(
+ fmt::format(
+ "OccPersistData: IPS enabled:{}, enter:{}%/{}s, exit:{}%/{}s",
+ modeData.ipsEnabled, modeData.ipsEnterUtil,
+ modeData.ipsEnterTime, modeData.ipsExitUtil,
+ modeData.ipsExitTime)
+ .c_str());
+ }
}
// Saves the OEM mode data in the filesystem using cereal.
void OccPersistData::save()
{
std::filesystem::path opath =
- std::filesystem::path{OCC_CONTROL_PERSIST_PATH} / oemModeFilename;
+ std::filesystem::path{OCC_CONTROL_PERSIST_PATH} / powerModeFilename;
if (!std::filesystem::exists(opath.parent_path()))
{
@@ -629,15 +634,16 @@
}
log<level::DEBUG>(
- fmt::format("OccPersistData::save: Writing OEM persisted data to {}",
- opath.c_str())
+ fmt::format(
+ "OccPersistData::save: Writing Power Mode persisted data to {}",
+ opath.c_str())
.c_str());
print();
std::ofstream stream{opath.c_str()};
cereal::JSONOutputArchive oarchive{stream};
- oarchive(oemData);
+ oarchive(modeData);
}
// Loads the OEM mode data in the filesystem using cereal.
@@ -645,24 +651,25 @@
{
std::filesystem::path ipath =
- std::filesystem::path{OCC_CONTROL_PERSIST_PATH} / oemModeFilename;
+ std::filesystem::path{OCC_CONTROL_PERSIST_PATH} / powerModeFilename;
if (!std::filesystem::exists(ipath))
{
+ modeData.modeInitialized = false;
+ modeData.ipsInitialized = false;
return;
}
log<level::DEBUG>(
- fmt::format("OccPersistData::load: Reading OEM persisted data from {}",
- ipath.c_str())
+ fmt::format(
+ "OccPersistData::load: Reading Power Mode persisted data from {}",
+ ipath.c_str())
.c_str());
try
{
std::ifstream stream{ipath.c_str()};
cereal::JSONInputArchive iarchive(stream);
- iarchive(oemData);
-
- oemSet = true;
+ iarchive(modeData);
}
catch (const std::exception& e)
{
@@ -671,28 +678,185 @@
fmt::format("OccPersistData::load: failed to read {}, errno={}",
ipath.c_str(), error)
.c_str());
+ modeData.modeInitialized = false;
+ modeData.ipsInitialized = false;
}
print();
}
-void OccPersistData::purge()
+// Called when PowerModeProperties defaults are available on DBus
+void PowerMode::defaultsReady(sdbusplus::message::message& msg)
{
- std::filesystem::path opath =
- std::filesystem::path{OCC_CONTROL_PERSIST_PATH} / oemModeFilename;
+ std::map<std::string, std::variant<std::string>> properties{};
+ std::string interface;
+ msg.read(interface, properties);
- if (!std::filesystem::exists(opath))
+ // If persistent data exists, then don't need to read defaults
+ if ((!persistedData.modeAvailable()) || (!persistedData.ipsAvailable()))
{
- return;
+ log<level::INFO>(
+ fmt::format(
+ "Default PowerModeProperties are now available (persistent modeAvail={}, ipsAvail={})",
+ persistedData.modeAvailable() ? 'y' : 'n',
+ persistedData.modeAvailable() ? 'y' : 'n')
+ .c_str());
+
+ // Read default power mode defaults and update DBus
+ initPersistentData();
+ }
+}
+
+// Get the default power mode from DBus and return true if success
+bool PowerMode::getDefaultMode(SysPwrMode& defaultMode)
+{
+ try
+ {
+ auto& bus = utils::getBus();
+ std::string path = "/";
+ std::string service =
+ utils::getServiceUsingSubTree(PMODE_DEFAULT_INTERFACE, path);
+ auto method =
+ bus.new_method_call(service.c_str(), path.c_str(),
+ "org.freedesktop.DBus.Properties", "Get");
+ method.append(PMODE_DEFAULT_INTERFACE, "PowerMode");
+ auto reply = bus.call(method);
+
+ std::variant<std::string> stateEntryValue;
+ reply.read(stateEntryValue);
+ auto propVal = std::get<std::string>(stateEntryValue);
+
+ const std::string fullModeString =
+ PMODE_INTERFACE + ".PowerMode."s + propVal;
+ defaultMode = powermode::convertStringToMode(fullModeString);
+ if (!VALID_POWER_MODE_SETTING(defaultMode))
+ {
+ log<level::ERR>(
+ fmt::format(
+ "PowerMode::getDefaultMode: Invalid default power mode found: {}",
+ defaultMode)
+ .c_str());
+ // If default was read but not valid, use Max Performance
+ defaultMode = SysPwrMode::MAX_PERF;
+ return true;
+ }
+ }
+ catch (const sdbusplus::exception::exception& e)
+ {
+ log<level::ERR>(
+ fmt::format("Unable to read Default Power Mode: {}", e.what())
+ .c_str());
+ return false;
}
- print();
- log<level::DEBUG>("OccPersistData::purge() Removing OEM data");
+ return true;
+}
- oemSet = false;
- oemData.oemMode = SysPwrMode::NO_CHANGE;
- oemData.oemModeFreq = 0x0000;
- remove(opath.c_str());
+/* Get the default Idle Power Saver properties and return true if successful */
+bool PowerMode::getDefaultIPSParms(bool& ipsEnabled, uint8_t& enterUtil,
+ uint16_t& enterTime, uint8_t& exitUtil,
+ uint16_t& exitTime)
+{
+ // Defaults:
+ ipsEnabled = true; // Enabled
+ 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, uint16_t, uint64_t>>
+ ipsProperties{};
+
+ // Get all IPS properties from DBus
+ try
+ {
+ auto& bus = utils::getBus();
+ std::string path = "/";
+ std::string service =
+ utils::getServiceUsingSubTree(PMODE_DEFAULT_INTERFACE, path);
+ auto method =
+ bus.new_method_call(service.c_str(), path.c_str(),
+ "org.freedesktop.DBus.Properties", "GetAll");
+ method.append(PMODE_DEFAULT_INTERFACE);
+ auto reply = bus.call(method);
+ reply.read(ipsProperties);
+ }
+ catch (const sdbusplus::exception::exception& e)
+ {
+ log<level::ERR>(
+ fmt::format(
+ "Unable to read Default Idle Power Saver parameters so it will be disabled: {}",
+ e.what())
+ .c_str());
+ return false;
+ }
+
+ auto ipsEntry = ipsProperties.find("IdlePowerSaverEnabled");
+ if (ipsEntry != ipsProperties.end())
+ {
+ ipsEnabled = std::get<bool>(ipsEntry->second);
+ }
+ else
+ {
+ log<level::ERR>(
+ "PowerMode::getDefaultIPSParms could not find property: IdlePowerSaverEnabled");
+ }
+
+ ipsEntry = ipsProperties.find("EnterUtilizationPercent");
+ if (ipsEntry != ipsProperties.end())
+ {
+ enterUtil = std::get<uint64_t>(ipsEntry->second);
+ }
+ else
+ {
+ log<level::ERR>(
+ "PowerMode::getDefaultIPSParms could not find property: EnterUtilizationPercent");
+ }
+
+ ipsEntry = ipsProperties.find("EnterUtilizationDwellTime");
+ if (ipsEntry != ipsProperties.end())
+ {
+ enterTime = std::get<uint64_t>(ipsEntry->second);
+ }
+ else
+ {
+ log<level::ERR>(
+ "PowerMode::getDefaultIPSParms could not find property: EnterUtilizationDwellTime");
+ }
+
+ ipsEntry = ipsProperties.find("ExitUtilizationPercent");
+ if (ipsEntry != ipsProperties.end())
+ {
+ exitUtil = std::get<uint64_t>(ipsEntry->second);
+ }
+ else
+ {
+ log<level::ERR>(
+ "PowerMode::getDefaultIPSParms could not find property: ExitUtilizationPercent");
+ }
+
+ ipsEntry = ipsProperties.find("ExitUtilizationDwellTime");
+ if (ipsEntry != ipsProperties.end())
+ {
+ exitTime = std::get<uint64_t>(ipsEntry->second);
+ }
+ else
+ {
+ log<level::ERR>(
+ "PowerMode::getDefaultIPSParms could not find property: ExitUtilizationDwellTime");
+ }
+
+ if (enterUtil > exitUtil)
+ {
+ log<level::ERR>(
+ fmt::format(
+ "ERROR: Default Idle Power Saver Enter Utilization ({}%) is > Exit Utilization ({}%) - using Exit for both",
+ enterUtil, exitUtil)
+ .c_str());
+ enterUtil = exitUtil;
+ }
+
+ return true;
}
} // namespace powermode