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/app.cpp b/app.cpp
index 0d6053c..94e00c4 100644
--- a/app.cpp
+++ b/app.cpp
@@ -4,6 +4,9 @@
#include "occ_events.hpp"
#include "occ_manager.hpp"
#include "utils.hpp"
+#ifdef POWER10
+#include "powermode.hpp"
+#endif
#include <org/open_power/OCC/Device/error.hpp>
#include <phosphor-logging/elog.hpp>
@@ -38,6 +41,10 @@
#ifdef READ_OCC_SENSORS
sdbusplus::server::manager::manager objManagerXyz(bus, OCC_SENSORS_ROOT);
#endif
+#ifdef POWER10
+ sdbusplus::server::manager::manager objManagerXyzControl(
+ bus, "/xyz/openbmc_project/control");
+#endif
open_power::occ::Manager mgr(eventP);
// Claim the bus since all the house keeping is done now
diff --git a/occ_manager.cpp b/occ_manager.cpp
index ee8575d..3160131 100644
--- a/occ_manager.cpp
+++ b/occ_manager.cpp
@@ -136,7 +136,9 @@
#ifdef POWER10
if (!pmode)
{
- pmode = std::make_unique<open_power::occ::powermode::PowerMode>(*this);
+ // Create the power mode object
+ pmode = std::make_unique<open_power::occ::powermode::PowerMode>(
+ *this, powermode::PMODE_PATH, powermode::PIPS_PATH);
}
#endif
@@ -166,7 +168,7 @@
if (!pcap)
{
pcap = std::make_unique<open_power::occ::powercap::PowerCap>(
- *statusObjects.front());
+ *statusObjects.back());
}
#ifdef POWER10
@@ -292,7 +294,9 @@
pcap = std::make_unique<open_power::occ::powercap::PowerCap>(
*statusObjects.front(), occMasterName);
#ifdef POWER10
- pmode = std::make_unique<open_power::occ::powermode::PowerMode>(*this);
+ pmode = std::make_unique<open_power::occ::powermode::PowerMode>(
+ *this, open_power::occ::powermode::PMODE_PATH,
+ open_power::occ::powermode::PIPS_PATH);
// Set the master OCC on the PowerMode object
pmode->setMasterOcc(path);
#endif
diff --git a/occ_status.cpp b/occ_status.cpp
index 0cb9b46..5abf6dd 100644
--- a/occ_status.cpp
+++ b/occ_status.cpp
@@ -39,15 +39,15 @@
lastState = 0;
// Call into Manager to let know that we have bound
- if (this->callBack)
+ if (this->managerCallBack)
{
- this->callBack(value);
+ this->managerCallBack(value);
}
}
else
{
#ifdef POWER10
- if (device.master())
+ if (pmode && device.master())
{
// Prevent mode changes
pmode->setMasterActive(false);
@@ -60,9 +60,9 @@
#endif
// Call into Manager to let know that we will unbind.
- if (this->callBack)
+ if (this->managerCallBack)
{
- this->callBack(value);
+ this->managerCallBack(value);
}
// Stop watching for errors
@@ -109,8 +109,11 @@
void Status::deviceError()
{
#ifdef POWER10
- // Prevent mode changes
- pmode->setMasterActive(false);
+ if (pmode && device.master())
+ {
+ // Prevent mode changes
+ pmode->setMasterActive(false);
+ }
#endif
// This would deem OCC inactive
@@ -204,7 +207,7 @@
#ifdef POWER10
if (OccState(state) == OccState::ACTIVE)
{
- if (device.master())
+ if (pmode && device.master())
{
// Set the master OCC on the PowerMode object
pmode->setMasterOcc(path);
diff --git a/occ_status.hpp b/occ_status.hpp
index 32041c7..6dab7dd 100644
--- a/occ_status.hpp
+++ b/occ_status.hpp
@@ -86,7 +86,7 @@
) :
Interface(utils::getBus(), getDbusPath(path).c_str(), true),
- path(path), callBack(callBack), instance(getInstance(path)),
+ path(path), managerCallBack(callBack), instance(getInstance(path)),
manager(managerRef),
#ifdef POWER10
pmode(powerModeRef),
@@ -206,7 +206,7 @@
/** @brief Callback handler to be invoked during property change.
* This is a handler in Manager class
*/
- std::function<void(bool)> callBack;
+ std::function<void(bool)> managerCallBack;
/** @brief OCC instance number. Ex, 0,1, etc */
unsigned int instance;
diff --git a/powercap.cpp b/powercap.cpp
index ffa65dd..2555d95 100644
--- a/powercap.cpp
+++ b/powercap.cpp
@@ -16,10 +16,6 @@
constexpr auto PCAP_PATH = "/xyz/openbmc_project/control/host0/power_cap";
constexpr auto PCAP_INTERFACE = "xyz.openbmc_project.Control.Power.Cap";
-constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
-constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper";
-constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper";
-
constexpr auto POWER_CAP_PROP = "PowerCap";
constexpr auto POWER_CAP_ENABLE_PROP = "PowerCapEnable";
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
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
diff --git a/utils.cpp b/utils.cpp
index b44d477..e9ccc88 100644
--- a/utils.cpp
+++ b/utils.cpp
@@ -72,9 +72,9 @@
/**
* @brief Sets a given object's property value
*
- * @param[in] object - Name of the object containing the property
+ * @param[in] objectPath - Name of the object containing the property
* @param[in] interface - Interface name containing the property
- * @param[in] property - Property name
+ * @param[in] propertyName - Property name
* @param[in] value - Property value
*/
void setProperty(const std::string& objectPath, const std::string& interface,
@@ -83,23 +83,34 @@
using namespace std::literals::string_literals;
std::variant<std::string> varValue(std::forward<std::string>(value));
- auto& bus = getBus();
- auto service = getService(objectPath, interface);
- if (service.empty())
+ try
{
- return;
+ auto& bus = getBus();
+ auto service = getService(objectPath, interface);
+ if (service.empty())
+ {
+ return;
+ }
+
+ auto method = bus.new_method_call(service.c_str(), objectPath.c_str(),
+ DBUS_PROPERTY_IFACE, "Set");
+ method.append(interface, propertyName, varValue);
+
+ auto reply = bus.call(method);
+ if (reply.is_method_error())
+ {
+ log<level::ERR>(
+ fmt::format("util::setProperty: Failed to set property {}",
+ propertyName)
+ .c_str());
+ }
}
-
- auto method = bus.new_method_call(service.c_str(), objectPath.c_str(),
- DBUS_PROPERTY_IFACE, "Set");
- method.append(interface, propertyName, varValue);
-
- auto reply = bus.call(method);
- if (reply.is_method_error())
+ catch (const std::exception& e)
{
+ auto error = errno;
log<level::ERR>(
- fmt::format("util::setProperty: Failed to set property {}",
- propertyName)
+ fmt::format("setProperty: failed to Set {}, errno={}, what={}",
+ propertyName.c_str(), error, e.what())
.c_str());
}
}
@@ -120,6 +131,54 @@
return paths;
}
+
+// Get the service and object path for an interface
+std::string getServiceUsingSubTree(const std::string& interface,
+ std::string& path)
+{
+ using Path = std::string;
+ using Intf = std::string;
+ using Serv = std::string;
+ using Intfs = std::vector<Intf>;
+ using Objects = std::map<Path, std::map<Serv, Intfs>>;
+ Serv service;
+ Objects rspObjects;
+
+ auto& bus = getBus();
+ auto method = bus.new_method_call(MAPPER_BUSNAME, MAPPER_OBJ_PATH,
+ MAPPER_IFACE, "GetSubTree");
+ method.append(path, 0, std::vector{interface});
+
+ auto mapperResponseMsg = bus.call(method);
+ mapperResponseMsg.read(rspObjects);
+ if (rspObjects.empty())
+ {
+ log<level::ERR>(
+ fmt::format(
+ "util::getServiceUsingSubTree: Failed getSubTree({},0,{})",
+ path.c_str(), interface)
+ .c_str());
+ }
+ else
+ {
+ path = rspObjects.begin()->first;
+ if (!rspObjects.begin()->second.empty())
+ {
+ service = rspObjects.begin()->second.begin()->first;
+ }
+ else
+ {
+ log<level::ERR>(
+ fmt::format(
+ "getServiceUsingSubTree: service not found for interface {} (path={})",
+ interface, path.c_str())
+ .c_str());
+ }
+ }
+
+ return service;
+}
+
} // namespace utils
} // namespace occ
} // namespace open_power
diff --git a/utils.hpp b/utils.hpp
index 4a57700..2b4b897 100644
--- a/utils.hpp
+++ b/utils.hpp
@@ -78,6 +78,17 @@
getSubtreePaths(const std::vector<std::string>& interfaces,
const std::string& path = "/");
+/**
+ * @brief Get the D-Bus service and object path for an interface
+ *
+ * @param[in] interface - D-Bus interface name
+ * @param[in,out] path - D-Bus object path
+ *
+ * @return D-Bus service name
+ */
+std::string getServiceUsingSubTree(const std::string& interface,
+ std::string& path);
+
} // namespace utils
} // namespace occ
} // namespace open_power