pseq: Call chassis hard power off on pgood fail

When chassis power good fails, call the chassis hard power off target.
This allows the components within to recognize that the power is now
off.

Signed-off-by: Jim Wright <jlwright@us.ibm.com>
Change-Id: I0adf6da3f9c1f0c84255b53c6abf0b3d66ef6e4c
diff --git a/phosphor-power-sequencer/src/power_control.cpp b/phosphor-power-sequencer/src/power_control.cpp
index fe844d5..7426932 100644
--- a/phosphor-power-sequencer/src/power_control.cpp
+++ b/phosphor-power-sequencer/src/power_control.cpp
@@ -17,6 +17,7 @@
 #include "power_control.hpp"
 
 #include "types.hpp"
+#include "utility.hpp"
 
 #include <fmt/format.h>
 
@@ -66,6 +67,7 @@
 {
     if (inStateTransition)
     {
+        // In transition between power on and off, check for timeout
         const auto now = std::chrono::steady_clock::now();
         if (now > pgoodTimeoutTime)
         {
@@ -78,6 +80,7 @@
     int pgoodState = pgoodLine.get_value();
     if (pgoodState != pgood)
     {
+        // Power good has changed since last read
         pgood = pgoodState;
         if (pgoodState == 0)
         {
@@ -91,8 +94,22 @@
     }
     if (pgoodState == state)
     {
+        // Power good matches requested state
         inStateTransition = false;
     }
+    else if (!inStateTransition && (pgoodState == 0))
+    {
+        // Not in power off state, not changing state, and power good is off
+        // Power good has failed, call for chassis hard power off
+        log<level::ERR>("Chassis pgood failure");
+
+        auto method =
+            bus.new_method_call(util::SYSTEMD_SERVICE, util::SYSTEMD_ROOT,
+                                util::SYSTEMD_INTERFACE, "StartUnit");
+        method.append(util::POWEROFF_TARGET);
+        method.append("replace");
+        bus.call_noreply(method);
+    }
 }
 
 void PowerControl::setPgoodTimeout(int t)