discover_system_state: apply power restore policy as early as BMC ready
Add a waitBmcReady() to monitor BMC state every second, this function
returns true if BMC enters ready state early or returns flase if
timeout reached.
This allows phosphor-diecover-system-state service can perform power
restore policy as early as BMC enters ready state.
Signed-off-by: Potin Lai <potin.lai@quantatw.com>
Change-Id: I3f1ef2957c9c8218d094b0e7643dc2eec03535b4
diff --git a/README.md b/README.md
index 041843c..7779d3f 100644
--- a/README.md
+++ b/README.md
@@ -96,8 +96,10 @@
reset. If the chassis or host is on/running then this service will not run. If
they are off then the `RestorePolicy` will be read and executed by PSM code.
-The `PowerRestoreDelay` property within the interface defines how long the
-service will wait before issuing the power on request.
+The `PowerRestoreDelay` property within the interface defines a maximum time the
+service will wait for the BMC to enter the `Ready` state before issuing the
+power on request, this allows host to be powered on as early as the BMC is
+ready.
## Only Allow System Boot When BMC Ready
diff --git a/discover_system_state.cpp b/discover_system_state.cpp
index 789e876..0a9c728 100644
--- a/discover_system_state.cpp
+++ b/discover_system_state.cpp
@@ -166,7 +166,7 @@
info(
"power_policy=ALWAYS_POWER_ON, powering host on ({DELAY}s delay)",
"DELAY", powerRestoreDelaySec.count());
- std::this_thread::sleep_for(powerRestoreDelayUsec);
+ utils::waitBmcReady(bus, powerRestoreDelaySec);
phosphor::state::manager::utils::setProperty(
bus, hostPath, HOST_BUSNAME, "RestartCause",
convertForMessage(
@@ -192,7 +192,7 @@
info(
"power_policy=ALWAYS_POWER_OFF, set requested state to off ({DELAY}s delay)",
"DELAY", powerRestoreDelaySec.count());
- std::this_thread::sleep_for(powerRestoreDelayUsec);
+ utils::waitBmcReady(bus, powerRestoreDelaySec);
// Read last requested state and re-request it to execute it
auto hostReqState = phosphor::state::manager::utils::getProperty(
bus, hostPath, HOST_BUSNAME, "RequestedHostTransition");
@@ -209,7 +209,7 @@
{
info("power_policy=RESTORE, restoring last state ({DELAY}s delay)",
"DELAY", powerRestoreDelaySec.count());
- std::this_thread::sleep_for(powerRestoreDelayUsec);
+ utils::waitBmcReady(bus, powerRestoreDelaySec);
// Read last requested state and re-request it to execute it
auto hostReqState = phosphor::state::manager::utils::getProperty(
bus, hostPath, HOST_BUSNAME, "RequestedHostTransition");
diff --git a/utils.cpp b/utils.cpp
index cad8ffd..95760cb 100644
--- a/utils.cpp
+++ b/utils.cpp
@@ -244,6 +244,20 @@
return true;
}
+bool waitBmcReady(sdbusplus::bus_t& bus, std::chrono::seconds timeout)
+{
+ while (timeout.count() != 0)
+ {
+ timeout--;
+ if (isBmcReady(bus))
+ {
+ return true;
+ }
+ std::this_thread::sleep_for(std::chrono::seconds(1));
+ }
+ return false;
+}
+
} // namespace utils
} // namespace manager
} // namespace state
diff --git a/utils.hpp b/utils.hpp
index fa65c31..49f62bf 100644
--- a/utils.hpp
+++ b/utils.hpp
@@ -95,6 +95,13 @@
*/
bool isBmcReady(sdbusplus::bus_t& bus);
+/** @brief Wait BMC to enter ready state or timeout reached.
+ *
+ * @param[in] bus - The Dbus bus object
+ * @param[in] timeout - Timeout in second
+ */
+bool waitBmcReady(sdbusplus::bus_t& bus, std::chrono::seconds timeout);
+
} // namespace utils
} // namespace manager
} // namespace state