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/occ_manager.cpp b/occ_manager.cpp
index 9b6f1c5..d24aa68 100644
--- a/occ_manager.cpp
+++ b/occ_manager.cpp
@@ -13,6 +13,7 @@
#include <chrono>
#include <cmath>
#include <filesystem>
+#include <fstream>
#include <regex>
namespace open_power
@@ -132,11 +133,11 @@
{
auto path = fs::path(OCC_CONTROL_ROOT) / occ;
- passThroughObjects.emplace_back(
- std::make_unique<PassThrough>(path.c_str()));
-
statusObjects.emplace_back(std::make_unique<Status>(
event, path.c_str(), *this,
+#ifdef POWER10
+ pmode,
+#endif
std::bind(std::mem_fn(&Manager::statusCallBack), this,
std::placeholders::_1)
#ifdef PLDM
@@ -146,27 +147,37 @@
#endif
));
- // Create the power cap monitor object for master occ (0)
- if (!pcap)
+ if (statusObjects.back()->isMasterOcc())
{
- pcap = std::make_unique<open_power::occ::powercap::PowerCap>(
- *statusObjects.front());
- }
+ log<level::INFO>(
+ fmt::format("Manager::createObjects(): OCC{} is the master",
+ statusObjects.back()->getOccInstanceID())
+ .c_str());
+ _pollTimer->setEnabled(false);
+
+ // Create the power cap monitor object for master OCC
+ if (!pcap)
+ {
+ pcap = std::make_unique<open_power::occ::powercap::PowerCap>(
+ *statusObjects.front());
+ }
#ifdef POWER10
- // Create the power mode monitor object for master occ (0)
- if (!pmode)
- {
- pmode = std::make_unique<open_power::occ::powermode::PowerMode>(
- *statusObjects.front());
- }
- // Create the idle power saver monitor object for master occ (0)
- if (!pips)
- {
- pips = std::make_unique<open_power::occ::powermode::PowerIPS>(
- *statusObjects.front());
- }
+ // Create the power mode object for master OCC
+ if (!pmode)
+ {
+ pmode = std::make_unique<open_power::occ::powermode::PowerMode>(
+ *this, path.c_str());
+ }
#endif
+ }
+
+ passThroughObjects.emplace_back(std::make_unique<PassThrough>(path.c_str()
+#ifdef POWER10
+ ,
+ pmode
+#endif
+ ));
}
void Manager::statusCallBack(bool status)
@@ -214,9 +225,8 @@
if (!_pollTimer->isEnabled())
{
log<level::INFO>(
- fmt::format(
- "Manager::statusCallBack(): {} OCCs will be polled every {} seconds",
- activeCount, pollInterval)
+ fmt::format("Manager: OCCs will be polled every {} seconds",
+ pollInterval)
.c_str());
// Send poll and start OCC poll timer
@@ -280,9 +290,7 @@
*statusObjects.front(), occMasterName);
#ifdef POWER10
pmode = std::make_unique<open_power::occ::powermode::PowerMode>(
- *statusObjects.front());
- pips = std::make_unique<open_power::occ::powermode::PowerIPS>(
- *statusObjects.front());
+ *this, path.c_str());
#endif
}
#endif
@@ -1013,7 +1021,8 @@
else
{
log<level::INFO>(
- fmt::format("validateOccMaster: OCC{} is master", masterInstance)
+ fmt::format("validateOccMaster: OCC{} is master of {} OCCs",
+ masterInstance, activeCount)
.c_str());
}
}