Implement processor throttle dbus properties
- create processor throttle dbus objects for each OCC (processor)
- update throttle properties based on OCC poll response data
or safe mode status.
Throttle data will be made available via Redfish
NAME TYPE SIGNATURE RESULT/VALUE FLAGS
org.freedesktop.DBus.Introspectable interface - - -
.Introspect method - s -
org.freedesktop.DBus.Peer interface - - -
.GetMachineId method - s -
.Ping method - - -
org.freedesktop.DBus.Properties interface - - -
.Get method ss v -
.GetAll method s a{sv} -
.Set method ssv - -
.PropertiesChanged signal sa{sv}as - -
xyz.openbmc_project.Control.Power.Throttle interface - - -
.ThrottleCauses property as 0 emits-change
.Throttled property b false emits-change
Example of throttled processor (due to a power limit):
as 1 "xyz.openbmc_project.Control.Power.Throttle.ThrottleReasons.PowerLimit"
Change-Id: I0af9d82fab9d694427d0adaa45f4a372d25fbc12
Signed-off-by: Chris Cain <cjcain@us.ibm.com>
diff --git a/occ_status.cpp b/occ_status.cpp
index 85b70ee..b89e469 100644
--- a/occ_status.cpp
+++ b/occ_status.cpp
@@ -18,6 +18,9 @@
using namespace phosphor::logging;
+using ThrottleObj =
+ sdbusplus::xyz::openbmc_project::Control::Power::server::Throttle;
+
// Handles updates to occActive property
bool Status::occActive(bool value)
{
@@ -28,6 +31,9 @@
.c_str());
if (value)
{
+ // Clear prior throttle reason (before setting device active)
+ updateThrottle(false, THROTTLED_ALL);
+
// Set the device active
device.setActive(true);
@@ -77,6 +83,9 @@
// Set the device inactive
device.setActive(false);
+
+ // Clear throttles (OCC not active after disabling device)
+ updateThrottle(false, THROTTLED_ALL);
}
}
else if (value && !device.active())
@@ -555,5 +564,121 @@
}
}
+// Update processor throttle status on dbus
+void Status::updateThrottle(const bool isThrottled, const uint8_t newReason)
+{
+ if (!throttleHandle)
+ {
+ return;
+ }
+
+ uint8_t newThrottleCause = throttleCause;
+
+ if (isThrottled) // throttled due to newReason
+ {
+ if ((newReason & throttleCause) == 0)
+ {
+ // set the bit(s) for passed in reason
+ newThrottleCause |= newReason;
+ }
+ // else no change
+ }
+ else // no longer throttled due to newReason
+ {
+ if ((newReason & throttleCause) != 0)
+ {
+ // clear the bit(s) for passed in reason
+ newThrottleCause &= ~newReason;
+ }
+ // else no change
+ }
+
+ if (newThrottleCause != throttleCause)
+ {
+ if (newThrottleCause == THROTTLED_NONE)
+ {
+ log<level::DEBUG>(
+ fmt::format(
+ "updateThrottle: OCC{} no longer throttled (prior reason: {})",
+ instance, throttleCause)
+ .c_str());
+ throttleCause = THROTTLED_NONE;
+ throttleHandle->throttled(false);
+ throttleHandle->throttleCauses({});
+ }
+ else
+ {
+ log<level::DEBUG>(
+ fmt::format(
+ "updateThrottle: OCC{} is throttled with reason {} (prior reason: {})",
+ instance, newThrottleCause, throttleCause)
+ .c_str());
+ throttleCause = newThrottleCause;
+
+ std::vector<ThrottleObj::ThrottleReasons> updatedCauses;
+ if (throttleCause & THROTTLED_POWER)
+ {
+ updatedCauses.push_back(
+ throttleHandle->ThrottleReasons::PowerLimit);
+ }
+ if (throttleCause & THROTTLED_THERMAL)
+ {
+ updatedCauses.push_back(
+ throttleHandle->ThrottleReasons::ThermalLimit);
+ }
+ if (throttleCause & THROTTLED_SAFE)
+ {
+ updatedCauses.push_back(
+ throttleHandle->ThrottleReasons::ManagementDetectedFault);
+ }
+ throttleHandle->throttleCauses(updatedCauses);
+ throttleHandle->throttled(true);
+ }
+ }
+ // else no change to throttle status
+}
+
+// Get processor path associated with this OCC
+void Status::readProcAssociation()
+{
+ std::string managingPath = path + "/power_managing";
+ log<level::DEBUG>(
+ fmt::format("readProcAssociation: getting endpoints for {} ({})",
+ managingPath, path)
+ .c_str());
+ try
+ {
+ utils::PropertyValue procPathProperty{};
+ procPathProperty = utils::getProperty(
+ managingPath, "xyz.openbmc_project.Association", "endpoints");
+ auto result = std::get<std::vector<std::string>>(procPathProperty);
+ if (result.size() > 0)
+ {
+ procPath = result[0];
+ log<level::INFO>(
+ fmt::format("readProcAssociation: OCC{} has proc={}", instance,
+ procPath.c_str())
+ .c_str());
+ }
+ else
+ {
+ log<level::ERR>(
+ fmt::format(
+ "readProcAssociation: No processor associated with OCC{} / {}",
+ instance, path)
+ .c_str());
+ }
+ }
+ catch (const sdbusplus::exception_t& e)
+ {
+ log<level::ERR>(
+ fmt::format(
+ "readProcAssociation: Unable to get proc assocated with {} - {}",
+ path, e.what())
+ .c_str());
+ procPath = {};
+ }
+}
+
} // namespace occ
} // namespace open_power