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.hpp b/powermode.hpp
index 0ec22a5..b212184 100644
--- a/powermode.hpp
+++ b/powermode.hpp
@@ -13,6 +13,8 @@
#include <cereal/types/vector.hpp>
#include <sdbusplus/bus.hpp>
#include <sdbusplus/bus/match.hpp>
+#include <xyz/openbmc_project/Control/Power/IdlePowerSaver/server.hpp>
+#include <xyz/openbmc_project/Control/Power/Mode/server.hpp>
#include <filesystem>
@@ -25,6 +27,10 @@
namespace powermode
{
+namespace Base = sdbusplus::xyz::openbmc_project::Control::Power::server;
+using ModeInterface = sdbusplus::server::object::object<Base::Mode>;
+using IpsInterface = sdbusplus::server::object::object<Base::IdlePowerSaver>;
+using namespace std::literals::string_literals;
constexpr auto PMODE_PATH = "/xyz/openbmc_project/control/host0/power_mode";
constexpr auto PMODE_INTERFACE = "xyz.openbmc_project.Control.Power.Mode";
@@ -39,6 +45,9 @@
constexpr auto IPS_EXIT_UTIL = "ExitUtilizationPercent";
constexpr auto IPS_EXIT_TIME = "ExitDwellTime";
+const auto PMODE_DEFAULT_INTERFACE =
+ "xyz.openbmc_project.Configuration.PowerModeProperties"s;
+
/** @brief Query the current Hypervisor target
* @return true if the current Hypervisor target is PowerVM
*/
@@ -52,17 +61,25 @@
*/
SysPwrMode convertStringToMode(const std::string& i_modeString);
-struct OemModeData
+struct PowerModeData
{
- SysPwrMode oemMode = SysPwrMode::NO_CHANGE;
- uint16_t oemModeFreq = 0x0000;
+ bool modeInitialized = false;
+ SysPwrMode mode = SysPwrMode::NO_CHANGE;
+ uint16_t oemModeData = 0x0000;
+ bool ipsInitialized = false;
+ bool ipsEnabled = true;
+ uint8_t ipsEnterUtil = 0;
+ uint16_t ipsEnterTime = 0;
+ uint8_t ipsExitUtil = 0;
+ uint16_t ipsExitTime = 0;
/** @brief Function specifying data to archive for cereal.
*/
template <class Archive>
void serialize(Archive& archive)
{
- archive(oemMode, oemModeFreq);
+ archive(modeInitialized, mode, oemModeData, ipsInitialized, ipsEnabled,
+ ipsEnterUtil, ipsEnterTime, ipsExitUtil, ipsExitTime);
}
};
@@ -80,7 +97,7 @@
OccPersistData(OccPersistData&&) = default;
OccPersistData& operator=(OccPersistData&&) = default;
- /** @brief Loads any saved OEM mode data */
+ /** @brief Loads any saved power mode data */
OccPersistData()
{
load();
@@ -88,52 +105,107 @@
/** @brief Save Power Mode data to persistent file
*
- * @param[in] newMode - desired OEM Power Mode
- * @param[in] modeData - data required by some OEM Power Modes
+ * @param[in] newMode - desired System Power Mode
+ * @param[in] oemModeData - data required by some OEM Power Modes
*/
- void writeModeFile(const SysPwrMode newMode, const uint16_t modeData)
+ void updateMode(const SysPwrMode newMode, const uint16_t oemModeData)
{
- oemData.oemMode = newMode;
- oemData.oemModeFreq = modeData;
- oemSet = true;
+ modeData.mode = newMode;
+ modeData.oemModeData = oemModeData;
+ modeData.modeInitialized = true;
save();
}
- /** @brief Return the OEM Power Mode and frequency if enabled
+ /** @brief Write Idle Power Saver parameters to persistent file
*
- * @param[out] newMode - OEM mode (if set, else data not changed)
- * @param[out] oemFreq - Frequency data for OEM mode
- *
- * @returns true if OEM mode was set
+ * @param[in] enabled - Idle Power Save status (true = enabled)
+ * @param[in] enterUtil - IPS Enter Utilization (%)
+ * @param[in] enterTime - IPS Enter Time (seconds)
+ * @param[in] exitUtil - IPS Exit Utilization (%)
+ * @param[in] exitTime - IPS Exit Time (seconds)
*/
- bool getOemMode(SysPwrMode& mode, uint16_t& freq) const
+ void updateIPS(const bool enabled, const uint8_t enterUtil,
+ const uint16_t enterTime, const uint8_t exitUtil,
+ const uint16_t exitTime)
{
- if (!oemSet)
+ modeData.ipsEnabled = enabled;
+ modeData.ipsEnterUtil = enterUtil;
+ modeData.ipsEnterTime = enterTime;
+ modeData.ipsExitUtil = exitUtil;
+ modeData.ipsExitTime = exitTime;
+ modeData.ipsInitialized = true;
+ save();
+ }
+
+ /** @brief Return the Power Mode and mode data
+ *
+ * @param[out] mode - current system power mode
+ * @param[out] oemModeData - frequency data for some OEM mode
+ *
+ * @returns true if mode was available
+ */
+ bool getMode(SysPwrMode& mode, uint16_t& oemModeData) const
+ {
+ if (!modeData.modeInitialized)
{
return false;
}
- mode = oemData.oemMode;
- freq = oemData.oemModeFreq;
+ mode = modeData.mode;
+ oemModeData = modeData.oemModeData;
return true;
}
+ /** @brief Get the Idle Power Saver properties from DBus
+ *
+ * @param[out] enabled - Idle Power Save status (true = enabled)
+ * @param[out] enterUtil - IPS Enter Utilization (%)
+ * @param[out] enterTime - IPS Enter Time (seconds)
+ * @param[out] exitUtil - IPS Exit Utilization (%)
+ * @param[out] exitTime - IPS Exit Time (seconds)
+ *
+ * @return true if parameters were read successfully
+ */
+ bool getIPS(bool& enabled, uint8_t& enterUtil, uint16_t& enterTime,
+ uint8_t& exitUtil, uint16_t& exitTime)
+ {
+ if (!modeData.ipsInitialized)
+ {
+ return false;
+ }
+
+ enabled = modeData.ipsEnabled;
+ enterUtil = modeData.ipsEnterUtil;
+ enterTime = modeData.ipsEnterTime;
+ exitUtil = modeData.ipsExitUtil;
+ exitTime = modeData.ipsExitTime;
+ return true;
+ }
+
+ /** @brief Return true if the power mode is available */
+ bool modeAvailable()
+ {
+ return (modeData.modeInitialized);
+ }
+
+ /** @brief Return true if the power mode is available */
+ bool ipsAvailable()
+ {
+ return (modeData.ipsInitialized);
+ }
+
/** @brief Saves the Power Mode data in the filesystem using cereal. */
void save();
- /** @brief Removes the OEM mode data. */
- void purge();
-
- inline void print();
+ /** @brief Trace the Power Mode and IPS parameters. */
+ void print();
private:
- static constexpr auto oemModeFilename = "oemModeData";
+ /** @brief Power Mode data filename to store persistent data */
+ static constexpr auto powerModeFilename = "powerModeData";
- /** @brief true if an OEM Power Mode was set */
- bool oemSet = false;
-
- /** @brief OEM Power Mode data */
- OemModeData oemData;
+ /** @brief Power Mode data object to be persisted */
+ PowerModeData modeData;
/** @brief Loads the OEM mode data in the filesystem using cereal. */
void load();
@@ -147,7 +219,7 @@
* the power mode to the OCC if the mode is changed while the occ is active.
*/
-class PowerMode
+class PowerMode : public ModeInterface, public IpsInterface
{
public:
/** @brief PowerMode object to inform occ of changes to mode
@@ -156,11 +228,14 @@
* If a change is detected, and the occ is active, then this object will
* notify the OCC of the change.
*
- * @param[in] managerRef -
- * @param[in] path -
+ * @param[in] managerRef - manager object reference
+ * @param[in] modePath - Power Mode dbus path
+ * @param[in] ipsPath - Idle Power Saver dbus path
*/
- explicit PowerMode(const Manager& managerRef) :
- manager(managerRef), occInstance(0),
+ explicit PowerMode(const Manager& managerRef, const char* modePath,
+ const char* ipsPath) :
+ ModeInterface(utils::getBus(), modePath, false),
+ IpsInterface(utils::getBus(), ipsPath, false), manager(managerRef),
pmodeMatch(utils::getBus(),
sdbusplus::bus::match::rules::propertiesChanged(
PMODE_PATH, PMODE_INTERFACE),
@@ -169,9 +244,44 @@
sdbusplus::bus::match::rules::propertiesChanged(
PIPS_PATH, PIPS_INTERFACE),
[this](auto& msg) { this->ipsChanged(msg); }),
- masterOccSet(false), masterActive(false){};
+ defaultsUpdateMatch(
+ utils::getBus(),
+ sdbusplus::bus::match::rules::propertiesChangedNamespace(
+ "/xyz/openbmc_project/inventory", PMODE_DEFAULT_INTERFACE),
+ [this](auto& msg) { this->defaultsReady(msg); }),
+ masterOccSet(false), masterActive(false)
+ {
+ // restore Power Mode to DBus
+ SysPwrMode currentMode;
+ uint16_t oemModeData = 0;
+ if (getMode(currentMode, oemModeData))
+ {
+ updateDbusMode(currentMode);
+ }
+ // restore Idle Power Saver parameters to DBus
+ uint8_t enterUtil, exitUtil;
+ uint16_t enterTime, exitTime;
+ bool ipsEnabled;
+ if (getIPSParms(ipsEnabled, enterUtil, enterTime, exitUtil, exitTime))
+ {
+ updateDbusIPS(ipsEnabled, enterUtil, enterTime, exitUtil, exitTime);
+ }
+ };
- bool setMode(const SysPwrMode newMode, const uint16_t modedata);
+ /** @brief Initialize the persistent data with default values
+ *
+ * @return true if initialization completed
+ */
+ bool initPersistentData();
+
+ /** @brief Set the current power mode property
+ *
+ * @param[in] newMode - desired system power mode
+ * @param[in] oemModeData - data required by some OEM Power Modes
+ *
+ * @return true if mode accepted
+ */
+ bool setMode(const SysPwrMode newMode, const uint16_t oemModeData);
/** @brief Send mode change command to the master OCC
* @return SUCCESS on success
@@ -218,6 +328,9 @@
/** @brief Used to subscribe to dbus IPS property changes **/
sdbusplus::bus::match_t ipsMatch;
+ /** @brief Used to subscribe to dbus defaults property changes **/
+ sdbusplus::bus::match_t defaultsUpdateMatch;
+
OccPersistData persistedData;
/** @brief True when the master OCC has been established */
@@ -235,10 +348,14 @@
*/
void modeChanged(sdbusplus::message::message& msg);
- /** @brief Get the current power mode property from DBus
- * @return Power mode
+ /** @brief Get the current power mode property
+ *
+ * @param[out] currentMode - current system power mode
+ * @param[out] oemModeData - frequency data for some OEM mode
+ *
+ * @return true if data read successfully
*/
- SysPwrMode getDbusMode();
+ bool getMode(SysPwrMode& currentMode, uint16_t& oemModeData);
/** @brief Update the power mode property on DBus
*
@@ -257,11 +374,60 @@
*/
void ipsChanged(sdbusplus::message::message& msg);
- /** @brief Get the Idle Power Saver properties from DBus
- * @return true if IPS is enabled
+ /** @brief Get the Idle Power Saver properties
+ *
+ * @param[out] enabled - Idle Power Save status (true = enabled)
+ * @param[out] enterUtil - IPS Enter Utilization (%)
+ * @param[out] enterTime - IPS Enter Time (seconds)
+ * @param[out] exitUtil - IPS Exit Utilization (%)
+ * @param[out] exitTime - IPS Exit Time (seconds)
+ *
+ * @return true if data read successfully
*/
- bool getIPSParms(uint8_t& enterUtil, uint16_t& enterTime, uint8_t& exitUtil,
- uint16_t& exitTime);
+ bool getIPSParms(bool& enabled, uint8_t& enterUtil, uint16_t& enterTime,
+ uint8_t& exitUtil, uint16_t& exitTime);
+
+ /** Update the Idle Power Saver data on DBus
+ *
+ * @param[in] enabled - Idle Power Save status (true = enabled)
+ * @param[in] enterUtil - IPS Enter Utilization (%)
+ * @param[in] enterTime - IPS Enter Time (seconds)
+ * @param[in] exitUtil - IPS Exit Utilization (%)
+ * @param[in] exitTime - IPS Exit Time (seconds)
+ *
+ * @return true if parameters were set successfully
+ */
+ bool updateDbusIPS(const bool enabled, const uint8_t enterUtil,
+ const uint16_t enterTime, const uint8_t exitUtil,
+ const uint16_t exitTime);
+
+ /** @brief Callback for entity manager default changes
+ *
+ * Called when PowerModeProperties defaults are available
+ */
+ void defaultsReady(sdbusplus::message::message& msg);
+
+ /** @brief Get the default power mode property for this system type
+ *
+ * @param[out] defaultMode - default system power mode
+ *
+ * @return true if data read successfully
+ */
+ bool getDefaultMode(SysPwrMode& defaultMode);
+
+ /** @brief Get the default Idle Power Saver properties for this system type
+ *
+ * @param[out] enabled - Idle Power Save status (true = enabled)
+ * @param[out] enterUtil - IPS Enter Utilization (%)
+ * @param[out] enterTime - IPS Enter Time (seconds)
+ * @param[out] exitUtil - IPS Exit Utilization (%)
+ * @param[out] exitTime - IPS Exit Time (seconds)
+ *
+ * @return true if parameters were read successfully
+ */
+ bool getDefaultIPSParms(bool& enabled, uint8_t& enterUtil,
+ uint16_t& enterTime, uint8_t& exitUtil,
+ uint16_t& exitTime);
};
} // namespace powermode