Add support for OEM Power Modes
- Allow mode to be set via PassThrough interface
- Allow non-customer OEM power modes to be persisted
- Persist any OEM power mode settings
- moved mode related code from Status to PowerMode object
- merged PowerIPS into PowerMode object
Tested on Everest and Rainier.
Setting mode through PassThrough/ce-login:
busctl call org.open_power.OCC.Control /org/open_power/control/occ0 org.open_power.OCC.PassThrough SetMode yq 11 3600
Trace (via PassThrough interface)
openpower-occ-control[4440]: PassThrough::setMode() Setting Power Mode 11 (data: 3600)
openpower-occ-control[4440]: PowerMode::sendModeChange: SET_MODE(11,3600) command to OCC0 (9 bytes)
Trace (setting mode via GUI/Redfish):
openpower-occ-control[4440]: Power Mode Change Requested: xyz.openbmc_project.Control.Power.Mode.PowerMode.MaximumPerformance
openpower-occ-control[4440]: PowerMode::sendModeChange: SET_MODE(12,0) command to OCC0 (9 bytes)
Verified when system in any OEM mode that Redfish also reports OEM
Verified all modes are persisted across PM Complex resets and reboots
Change-Id: Idd0be05cb6fd74dbd0776145f212c49addd1c365
Signed-off-by: Chris Cain <cjcain@us.ibm.com>
diff --git a/powermode.hpp b/powermode.hpp
index 0d337dc..5342c77 100644
--- a/powermode.hpp
+++ b/powermode.hpp
@@ -3,8 +3,14 @@
#include "config.h"
#ifdef POWER10
-#include "occ_status.hpp"
+#include "occ_command.hpp"
+#include <cereal/archives/json.hpp>
+//#include <cereal/archives/binary.hpp>
+#include <cereal/cereal.hpp>
+#include <cereal/types/string.hpp>
+#include <cereal/types/tuple.hpp>
+#include <cereal/types/vector.hpp>
#include <sdbusplus/bus.hpp>
#include <sdbusplus/bus/match.hpp>
@@ -14,6 +20,9 @@
{
namespace occ
{
+
+class Manager;
+
namespace powermode
{
@@ -30,6 +39,11 @@
constexpr auto IPS_EXIT_UTIL = "ExitUtilizationPercent";
constexpr auto IPS_EXIT_TIME = "ExitDwellTime";
+/** @brief Query the current Hypervisor target
+ * @return true if the current Hypervisor target is PowerVM
+ */
+bool isPowerVM();
+
/** @brief Convert power mode string to OCC SysPwrMode value
*
* @param[in] i_modeString - power mode string
@@ -38,6 +52,93 @@
*/
SysPwrMode convertStringToMode(const std::string& i_modeString);
+struct OemModeData
+{
+ SysPwrMode oemMode = SysPwrMode::NO_CHANGE;
+ uint16_t oemModeFreq = 0x0000;
+
+ /** @brief Function specifying data to archive for cereal.
+ */
+ template <class Archive>
+ void serialize(Archive& archive)
+ {
+ archive(oemMode, oemModeFreq);
+ }
+};
+
+/** @class OccPersistData
+ * @brief Provides persistent container to store data for OCC
+ *
+ * Data is stored via cereal
+ */
+class OccPersistData
+{
+ public:
+ ~OccPersistData() = default;
+ OccPersistData(const OccPersistData&) = default;
+ OccPersistData& operator=(const OccPersistData&) = default;
+ OccPersistData(OccPersistData&&) = default;
+ OccPersistData& operator=(OccPersistData&&) = default;
+
+ /** @brief Loads any saved OEM mode data */
+ OccPersistData()
+ {
+ load();
+ }
+
+ /** @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
+ */
+ void writeModeFile(const SysPwrMode newMode, const uint16_t modeData)
+ {
+ oemData.oemMode = newMode;
+ oemData.oemModeFreq = modeData;
+ oemSet = true;
+ save();
+ }
+
+ /** @brief Return the OEM Power Mode and frequency if enabled
+ *
+ * @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
+ */
+ bool getOemMode(SysPwrMode& mode, uint16_t& freq) const
+ {
+ if (!oemSet)
+ {
+ return false;
+ }
+
+ mode = oemData.oemMode;
+ freq = oemData.oemModeFreq;
+ return true;
+ }
+
+ /** @brief Saves the Power Mode data in the filesystem using cereal. */
+ void save();
+
+ /** @brief Removes the OEM mode data. */
+ void purge();
+
+ inline void print();
+
+ private:
+ static constexpr auto oemModeFilename = "oemModeData";
+
+ /** @brief true if an OEM Power Mode was set */
+ bool oemSet = false;
+
+ /** @brief OEM Power Mode data */
+ OemModeData oemData;
+
+ /** @brief Loads the OEM mode data in the filesystem using cereal. */
+ void load();
+};
+
/** @class PowerMode
* @brief Monitors for changes to the power mode and notifies occ
*
@@ -55,16 +156,67 @@
* If a change is detected, and the occ is active, then this object will
* notify the OCC of the change.
*
- * @param[in] occStatus - The occ status object
+ * @param[in] managerRef -
+ * @param[in] path -
*/
- explicit PowerMode(Status& occStatus) :
- occStatus(occStatus),
+ explicit PowerMode(Manager& managerRef, const char* path) :
+ manager(managerRef), path(path), occInstance(this->path.back() - '0'),
+ occCmd(occInstance, path),
pmodeMatch(utils::getBus(),
sdbusplus::bus::match::rules::propertiesChanged(
PMODE_PATH, PMODE_INTERFACE),
- [this](auto& msg) { this->modeChanged(msg); }){};
+ [this](auto& msg) { this->modeChanged(msg); }),
+ ipsMatch(utils::getBus(),
+ sdbusplus::bus::match::rules::propertiesChanged(
+ PIPS_PATH, PIPS_INTERFACE),
+ [this](auto& msg) { this->ipsChanged(msg); }),
+ masterActive(false){};
+
+ bool setMode(const SysPwrMode newMode, const uint16_t modedata);
+
+ /** @brief Send mode change command to the master OCC
+ * @return SUCCESS on success
+ */
+ CmdStatus sendModeChange();
+
+ /** @brief Send Idle Power Saver config data to the master OCC
+ * @return SUCCESS on success
+ */
+ CmdStatus sendIpsData();
+
+ /** @brief Notify object of master OCC state. If not acitve, no
+ * commands will be sent to the master OCC
+ *
+ * @param[in] isActive - true when master OCC is active
+ */
+ void setMasterActive(const bool isActive = true)
+ {
+ masterActive = isActive;
+ };
private:
+ /** @brief OCC manager object */
+ const Manager& manager;
+
+ /** @brief Pass-through occ path on the bus */
+ std::string path;
+
+ /** @brief OCC instance number */
+ int occInstance;
+
+ /** @brief Object to send commands to the OCC */
+ OccCommand occCmd;
+
+ /** @brief Used to subscribe to dbus pmode property changes **/
+ sdbusplus::bus::match_t pmodeMatch;
+
+ /** @brief Used to subscribe to dbus IPS property changes **/
+ sdbusplus::bus::match_t ipsMatch;
+
+ OccPersistData persistedData;
+
+ bool masterActive;
+
/** @brief Callback for pmode setting changes
*
* Process change and inform OCC
@@ -74,47 +226,33 @@
*/
void modeChanged(sdbusplus::message::message& msg);
- /* @brief OCC Status object */
- Status& occStatus;
-
- /** @brief Used to subscribe to dbus pmode property changes **/
- sdbusplus::bus::match_t pmodeMatch;
-};
-
-class PowerIPS
-{
- public:
- /** @brief PowerIPS object to inform occ of changes to Idle Power Saver
- * parms
- *
- * This object will monitor for changes to the Idle Power Saver settings.
- * If a change is detected, and the occ is active, then this object will
- * notify the OCC of the change.
- *
- * @param[in] occStatus - The occ status object
+ /** @brief Get the current power mode property from DBus
+ * @return Power mode
*/
- explicit PowerIPS(Status& occStatus) :
- occStatus(occStatus),
- ipsMatch(utils::getBus(),
- sdbusplus::bus::match::rules::propertiesChanged(
- PIPS_PATH, PIPS_INTERFACE),
- [this](auto& msg) { this->ipsChanged(msg); }){};
+ SysPwrMode getDbusMode();
- private:
+ /** @brief Update the power mode property on DBus
+ *
+ * @param[in] newMode - desired power mode
+ *
+ * @return true on success
+ */
+ bool updateDbusMode(const SysPwrMode newMode);
+
/** @brief Callback for IPS setting changes
*
* Process change and inform OCC
*
- * @param[in] msg - Data associated with IPS change signal
+ * @param[in] msg - Data associated with IPS change signal
*
*/
void ipsChanged(sdbusplus::message::message& msg);
- /* @brief OCC Status object */
- Status& occStatus;
-
- /** @brief Used to subscribe to dbus IPS property changes **/
- sdbusplus::bus::match_t ipsMatch;
+ /** @brief Get the Idle Power Saver properties from DBus
+ * @return true if IPS is enabled
+ */
+ bool getIPSParms(uint8_t& enterUtil, uint16_t& enterTime, uint8_t& exitUtil,
+ uint16_t& exitTime);
};
} // namespace powermode