pseq: Observe minimum power off time
In order to give hardware components an appropriate time to discharge
and prevent thrashing during brownouts, enforce a minimum power off
time. A 25 second minimum delay will be enforced after power off before
the next power on. A minimum of 15 seconds must pass after cold start
until a power on will start.
Signed-off-by: Jim Wright <jlwright@us.ibm.com>
Change-Id: Ib0cd0bcda1ca492548ee7912bab9a46181337098
diff --git a/phosphor-power-sequencer/src/power_control.cpp b/phosphor-power-sequencer/src/power_control.cpp
index 7f6ef9f..9ed3878 100644
--- a/phosphor-power-sequencer/src/power_control.cpp
+++ b/phosphor-power-sequencer/src/power_control.cpp
@@ -19,6 +19,7 @@
#include "types.hpp"
#include "ucd90320_monitor.hpp"
+#include <fmt/chrono.h>
#include <fmt/format.h>
#include <phosphor-logging/elog-errors.hpp>
@@ -49,6 +50,7 @@
"xyz.openbmc_project.EntityManager"),
std::bind(&PowerControl::interfacesAddedHandler, this,
std::placeholders::_1)},
+ powerOnAllowedTime{std::chrono::steady_clock::now() + minimumColdStartTime},
timer{event, std::bind(&PowerControl::pollPgood, this), pollInterval}
{
// Obtain dbus service name
@@ -243,6 +245,21 @@
// other BMC applications time to complete power off processing
std::this_thread::sleep_for(std::chrono::seconds(2));
}
+ else
+ {
+ // If minimum power off time has not passed, wait
+ if (powerOnAllowedTime > std::chrono::steady_clock::now())
+ {
+ log<level::INFO>(
+ fmt::format(
+ "Waiting {} seconds until power on allowed",
+ std::chrono::duration_cast<std::chrono::seconds>(
+ powerOnAllowedTime - std::chrono::steady_clock::now())
+ .count())
+ .c_str());
+ }
+ std::this_thread::sleep_until(powerOnAllowedTime);
+ }
log<level::INFO>(fmt::format("setState: {}", s).c_str());
powerControlLine.request(
@@ -250,6 +267,13 @@
powerControlLine.set_value(s);
powerControlLine.release();
+ if (s == 0)
+ {
+ // Set a minimum amount of time to wait before next power on
+ powerOnAllowedTime =
+ std::chrono::steady_clock::now() + minimumPowerOffTime;
+ }
+
pgoodTimeoutTime = std::chrono::steady_clock::now() + timeout;
inStateTransition = true;
state = s;