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_pass_through.cpp b/occ_pass_through.cpp
index db133b1..6cf6374 100644
--- a/occ_pass_through.cpp
+++ b/occ_pass_through.cpp
@@ -22,8 +22,21 @@
namespace occ
{
-PassThrough::PassThrough(const char* path) :
- Iface(utils::getBus(), path), path(path),
+using namespace phosphor::logging;
+using namespace sdbusplus::org::open_power::OCC::Device::Error;
+
+PassThrough::PassThrough(
+ const char* path
+#ifdef POWER10
+ ,
+ std::unique_ptr<open_power::occ::powermode::PowerMode>& powerModeRef
+#endif
+ ) :
+ Iface(utils::getBus(), path),
+ path(path),
+#ifdef POWER10
+ pmode(powerModeRef),
+#endif
devicePath(OCC_DEV_PATH + std::to_string((this->path.back() - '0') + 1)),
occInstance(this->path.back() - '0'),
activeStatusSignal(
@@ -60,9 +73,6 @@
std::vector<uint8_t> PassThrough::send(std::vector<uint8_t> command)
{
- using namespace phosphor::logging;
- using namespace sdbusplus::org::open_power::OCC::Device::Error;
-
std::vector<uint8_t> response{};
log<level::DEBUG>(
@@ -100,6 +110,48 @@
return response;
}
+bool PassThrough::setMode(const uint8_t mode, const uint16_t modeData)
+{
+#ifdef POWER10
+ SysPwrMode newMode = SysPwrMode(mode);
+
+ if ((!VALID_POWER_MODE_SETTING(newMode)) &&
+ (!VALID_OEM_POWER_MODE_SETTING(newMode)))
+ {
+ log<level::ERR>(
+ fmt::format(
+ "PassThrough::setMode() Unsupported mode {} requested (0x{:04X})",
+ newMode, modeData)
+ .c_str());
+ return false;
+ }
+
+ if (((newMode == SysPwrMode::FFO) || (newMode == SysPwrMode::SFP)) &&
+ (modeData == 0))
+ {
+ log<level::ERR>(
+ fmt::format(
+ "PassThrough::setMode() Mode {} requires non-zero frequency point.",
+ newMode)
+ .c_str());
+ return false;
+ }
+
+ log<level::INFO>(
+ fmt::format("PassThrough::setMode() Setting Power Mode {} (data: {})",
+ newMode, modeData)
+ .c_str());
+ return pmode->setMode(newMode, modeData);
+#else
+ log<level::DEBUG>(
+ fmt::format(
+ "PassThrough::setMode() No support to setting Power Mode {} (data: {})",
+ mode, modeData)
+ .c_str());
+ return false;
+#endif
+}
+
// Called at OCC Status change signal
void PassThrough::activeStatusEvent(sdbusplus::message::message& msg)
{