pseq: Create dump on runtime pgood failure

Currently no dump is created when a power good failure occurs at
runtime. Add the call to create a dump.

Signed-off-by: Jim Wright <jlwright@us.ibm.com>
Change-Id: I1effbf13f0b2fd234deea96171efa289f9fa2380
diff --git a/phosphor-power-sequencer/src/power_control.cpp b/phosphor-power-sequencer/src/power_control.cpp
index 78a1d74..eac5ba4 100644
--- a/phosphor-power-sequencer/src/power_control.cpp
+++ b/phosphor-power-sequencer/src/power_control.cpp
@@ -155,7 +155,9 @@
         const auto now = std::chrono::steady_clock::now();
         if (now > pgoodTimeoutTime)
         {
-            log<level::ERR>("ERROR PowerControl: Pgood poll timeout");
+            log<level::ERR>(
+                fmt::format("Power state transition timeout, state: {}", state)
+                    .c_str());
             inStateTransition = false;
 
             if (state)
@@ -203,11 +205,11 @@
     else if (!inStateTransition && (pgoodState == 0) && !failureFound)
     {
         // Not in power off state, not changing state, and power good is off
+        log<level::ERR>("Chassis pgood failure");
         device->onFailure(false, powerSupplyError);
         failureFound = true;
-        // Power good has failed, call for chassis hard power off
-        log<level::ERR>("Chassis pgood failure");
 
+        // Power good has failed, call for chassis hard power off
         auto method =
             bus.new_method_call(util::SYSTEMD_SERVICE, util::SYSTEMD_ROOT,
                                 util::SYSTEMD_INTERFACE, "StartUnit");
diff --git a/phosphor-power-sequencer/src/power_control.hpp b/phosphor-power-sequencer/src/power_control.hpp
index 0670876..f659744 100644
--- a/phosphor-power-sequencer/src/power_control.hpp
+++ b/phosphor-power-sequencer/src/power_control.hpp
@@ -37,8 +37,8 @@
 
     /**
      * Creates a controller object for power on and off.
-     * @param[in] bus D-Bus bus object
-     * @param[in] event event object
+     * @param bus D-Bus bus object
+     * @param event event object
      */
     PowerControl(sdbusplus::bus::bus& bus, const sdeventplus::Event& event);
 
@@ -133,7 +133,7 @@
     static constexpr std::chrono::milliseconds pollInterval{3000};
 
     /**
-     * GPIO line object for power-on / power-off control
+     * GPIO line object for power on / power off control
      */
     gpiod::line powerControlLine;
 
@@ -164,7 +164,7 @@
 
     /**
      * Get the device properties
-     * @param[in] properties A map of property names and values
+     * @param properties A map of property names and values
      */
     void getDeviceProperties(util::DbusPropertyMap& properties);
 
diff --git a/phosphor-power-sequencer/src/power_interface.cpp b/phosphor-power-sequencer/src/power_interface.cpp
index d266ee1..06e17da 100644
--- a/phosphor-power-sequencer/src/power_interface.cpp
+++ b/phosphor-power-sequencer/src/power_interface.cpp
@@ -34,7 +34,7 @@
 {
 
 PowerInterface::PowerInterface(sdbusplus::bus::bus& bus, const char* path) :
-    _serverInterface(bus, path, POWER_IFACE, _vtable, this)
+    serverInterface(bus, path, POWER_IFACE, vtable, this)
 {}
 
 int PowerInterface::callbackGetPgood(sd_bus* /*bus*/, const char* /*path*/,
@@ -286,23 +286,23 @@
 void PowerInterface::emitPowerGoodSignal()
 {
     log<level::INFO>("emitPowerGoodSignal");
-    _serverInterface.new_signal("PowerGood").signal_send();
+    serverInterface.new_signal("PowerGood").signal_send();
 }
 
 void PowerInterface::emitPowerLostSignal()
 {
     log<level::INFO>("emitPowerLostSignal");
-    _serverInterface.new_signal("PowerLost").signal_send();
+    serverInterface.new_signal("PowerLost").signal_send();
 }
 
 void PowerInterface::emitPropertyChangedSignal(const char* property)
 {
     log<level::INFO>(
         fmt::format("emitPropertyChangedSignal: {}", property).c_str());
-    _serverInterface.property_changed(property);
+    serverInterface.property_changed(property);
 }
 
-const sdbusplus::vtable::vtable_t PowerInterface::_vtable[] = {
+const sdbusplus::vtable::vtable_t PowerInterface::vtable[] = {
     sdbusplus::vtable::start(),
     // Method setPowerState takes an int parameter and returns void
     sdbusplus::vtable::method("setPowerState", "i", "", callbackSetPowerState),
diff --git a/phosphor-power-sequencer/src/power_interface.hpp b/phosphor-power-sequencer/src/power_interface.hpp
index 0a3dae0..e4bf8cd 100644
--- a/phosphor-power-sequencer/src/power_interface.hpp
+++ b/phosphor-power-sequencer/src/power_interface.hpp
@@ -26,9 +26,9 @@
     virtual ~PowerInterface() = default;
 
     /**
-     * @brief Constructor to put object onto bus at a dbus path.
-     * @param[in] bus D-Bus bus object
-     * @param[in] path D-Bus object path
+     * Constructor to put object onto bus at a dbus path.
+     * @param bus D-Bus bus object
+     * @param path D-Bus object path
      */
     PowerInterface(sdbusplus::bus::bus& bus, const char* path);
 
@@ -44,7 +44,7 @@
 
     /**
      * Emit the property changed signal
-     * @param[in] property the property that changed
+     * @param property the property that changed
      */
     void emitPropertyChangedSignal(const char* property);
 
@@ -68,22 +68,20 @@
 
     /**
      * Sets the power good timeout
-     * @param[in] timeout power good timeout
+     * @param timeout power good timeout
      */
     virtual void setPgoodTimeout(int timeout) = 0;
 
     /**
      * Initiates a chassis power state change
-     * @param[in] state power state. Request power on with a value of 1. Request
+     * @param state power state. Request power on with a value of 1. Request
      * power off with a value of 0. Other values will be rejected.
      */
     virtual void setState(int state) = 0;
 
     /**
-     * Sets the power supply error. The error should be of great enough severity
-     * that a power good failure may occur and will be issued in preference to
-     * the power good error.
-     * @param[in] error power supply error. The value should be a message
+     * Sets the power supply error.
+     * @param error power supply error. The value should be a message
      * argument for a phosphor-logging Create call, e.g.
      * "xyz.openbmc_project.Power.PowerSupply.Error.PSKillFault"
      */
@@ -93,14 +91,14 @@
     /**
      * Holder for the instance of this interface to be on dbus
      */
-    sdbusplus::server::interface::interface _serverInterface;
+    sdbusplus::server::interface::interface serverInterface;
 
     /**
      * Systemd vtable structure that contains all the
      * methods, signals, and properties of this interface with their
      * respective systemd attributes
      */
-    static const sdbusplus::vtable::vtable_t _vtable[];
+    static const sdbusplus::vtable::vtable_t vtable[];
 
     /**
      * Systemd bus callback for getting the pgood property
diff --git a/phosphor-power-sequencer/src/power_sequencer_monitor.cpp b/phosphor-power-sequencer/src/power_sequencer_monitor.cpp
index df723ab..04398eb 100644
--- a/phosphor-power-sequencer/src/power_sequencer_monitor.cpp
+++ b/phosphor-power-sequencer/src/power_sequencer_monitor.cpp
@@ -33,6 +33,25 @@
     bus(bus)
 {}
 
+void PowerSequencerMonitor::createBmcDump()
+{
+    try
+    {
+        auto method = bus.new_method_call(
+            "xyz.openbmc_project.Dump.Manager", "/xyz/openbmc_project/dump/bmc",
+            "xyz.openbmc_project.Dump.Create", "CreateDump");
+        method.append(
+            std::vector<
+                std::pair<std::string, std::variant<std::string, uint64_t>>>());
+        bus.call_noreply(method);
+    }
+    catch (const sdbusplus::exception::exception& e)
+    {
+        log<level::ERR>(
+            fmt::format("Unable to create dump, error {}", e.what()).c_str());
+    }
+}
+
 void PowerSequencerMonitor::logError(
     const std::string& message,
     std::map<std::string, std::string>& additionalData)
@@ -83,6 +102,10 @@
         // Default to generic pgood error
         logError("xyz.openbmc_project.Power.Error.Shutdown", additionalData);
     }
+    if (!timeout)
+    {
+        createBmcDump();
+    }
 }
 
 } // namespace phosphor::power::sequencer
diff --git a/phosphor-power-sequencer/src/power_sequencer_monitor.hpp b/phosphor-power-sequencer/src/power_sequencer_monitor.hpp
index e8b36fc..eb151ce 100644
--- a/phosphor-power-sequencer/src/power_sequencer_monitor.hpp
+++ b/phosphor-power-sequencer/src/power_sequencer_monitor.hpp
@@ -24,14 +24,14 @@
 
     /**
      * Create a base device object for power sequence monitoring.
-     * @param[in] bus D-Bus bus object
+     * @param bus D-Bus bus object
      */
     explicit PowerSequencerMonitor(sdbusplus::bus::bus& bus);
 
     /**
      * Logs an error using the D-Bus Create method.
-     * @param[in] message Message property of the error log entry
-     * @param[in] additionalData AdditionalData property of the error log entry
+     * @param message Message property of the error log entry
+     * @param additionalData AdditionalData property of the error log entry
      */
     void logError(const std::string& message,
                   std::map<std::string, std::string>& additionalData);
@@ -39,8 +39,8 @@
     /**
      * Analyzes the device for errors when the device is
      * known to be in an error state.  A log will be created.
-     * @param[in] timeout if the failure state was determined by timing out
-     * @param[in] powerSupplyError The power supply error to log. A default
+     * @param timeout if the failure state was determined by timing out
+     * @param powerSupplyError The power supply error to log. A default
      * std:string, i.e. empty string (""), is passed when there is no power
      * supply error to log.
      */
@@ -51,6 +51,11 @@
      * The D-Bus bus object
      */
     sdbusplus::bus::bus& bus;
+
+    /*
+     * Create a BMC Dump
+     */
+    void createBmcDump();
 };
 
 } // namespace phosphor::power::sequencer
diff --git a/phosphor-power-sequencer/src/ucd90320_monitor.cpp b/phosphor-power-sequencer/src/ucd90320_monitor.cpp
index 32c883c..518f483 100644
--- a/phosphor-power-sequencer/src/ucd90320_monitor.cpp
+++ b/phosphor-power-sequencer/src/ucd90320_monitor.cpp
@@ -28,6 +28,7 @@
 
 #include <fstream>
 #include <map>
+#include <span>
 #include <string>
 
 namespace phosphor::power::sequencer
@@ -241,7 +242,7 @@
                     .c_str());
         }
         log<level::DEBUG>(
-            fmt::format("Found number of pins: {}", rails.size()).c_str());
+            fmt::format("Found number of pins: {}", pins.size()).c_str());
     }
     catch (const std::exception& e)
     {
@@ -261,13 +262,7 @@
     try
     {
         onFailureCheckRails(message, additionalData, powerSupplyError);
-        log<level::INFO>(
-            fmt::format("After onFailureCheckRails, message: {}", message)
-                .c_str());
         onFailureCheckPins(message, additionalData);
-        log<level::INFO>(
-            fmt::format("After onFailureCheckPins, message: {}", message)
-                .c_str());
     }
     catch (device_error::ReadFailure& e)
     {
@@ -285,6 +280,10 @@
                           : "xyz.openbmc_project.Power.Error.Shutdown";
     }
     logError(message, additionalData);
+    if (!timeout)
+    {
+        createBmcDump();
+    }
 }
 
 void UCD90320Monitor::onFailureCheckPins(
@@ -301,18 +300,65 @@
     // Workaround libgpiod bulk line maximum by getting values from individual
     // lines
     std::vector<int> values;
-    for (unsigned int offset = 0; offset < numberLines; ++offset)
+    try
     {
-        gpiod::line line = chip.get_line(offset);
-        line.request({"phosphor-power-control",
-                      gpiod::line_request::DIRECTION_INPUT, 0});
-        values.push_back(line.get_value());
-        line.release();
+        for (unsigned int offset = 0; offset < numberLines; ++offset)
+        {
+            gpiod::line line = chip.get_line(offset);
+            line.request({"phosphor-power-control",
+                          gpiod::line_request::DIRECTION_INPUT, 0});
+            values.push_back(line.get_value());
+            line.release();
+        }
+    }
+    catch (const std::exception& e)
+    {
+        log<level::ERR>(
+            fmt::format("Error reading device GPIOs, error {}", e.what())
+                .c_str());
+        additionalData.emplace("GPIO_ERROR", e.what());
     }
 
-    // Add GPIO values to additional data
-    log<level::INFO>(fmt::format("GPIO values: {}", values).c_str());
-    additionalData.emplace("GPIO_VALUES", fmt::format("{}", values));
+    // Add GPIO values to additional data, device has 84 GPIO pins so that value
+    // is expected
+    if (numberLines == 84)
+    {
+        log<level::INFO>(fmt::format("MAR01-24 GPIO values: {}",
+                                     std::span{values}.subspan(0, 24))
+                             .c_str());
+        additionalData.emplace(
+            "MAR01_24_GPIO_VALUES",
+            fmt::format("{}", std::span{values}.subspan(0, 24)));
+        log<level::INFO>(fmt::format("EN1-32 GPIO values: {}",
+                                     std::span{values}.subspan(24, 32))
+                             .c_str());
+        additionalData.emplace(
+            "EN1_32_GPIO_VALUES",
+            fmt::format("{}", std::span{values}.subspan(24, 32)));
+        log<level::INFO>(fmt::format("LGP01-16 GPIO values: {}",
+                                     std::span{values}.subspan(56, 16))
+                             .c_str());
+        additionalData.emplace(
+            "LGP01_16_GPIO_VALUES",
+            fmt::format("{}", std::span{values}.subspan(56, 16)));
+        log<level::INFO>(fmt::format("DMON1-8 GPIO values: {}",
+                                     std::span{values}.subspan(72, 8))
+                             .c_str());
+        additionalData.emplace(
+            "DMON1_8_GPIO_VALUES",
+            fmt::format("{}", std::span{values}.subspan(72, 8)));
+        log<level::INFO>(fmt::format("GPIO1-4 GPIO values: {}",
+                                     std::span{values}.subspan(80, 4))
+                             .c_str());
+        additionalData.emplace(
+            "GPIO1_4_GPIO_VALUES",
+            fmt::format("{}", std::span{values}.subspan(80, 4)));
+    }
+    else
+    {
+        log<level::INFO>(fmt::format("GPIO values: {}", values).c_str());
+        additionalData.emplace("GPIO_VALUES", fmt::format("{}", values));
+    }
 
     // Only check GPIOs if no rail fail was found
     if (message.empty())
@@ -328,8 +374,6 @@
                     additionalData.emplace("INPUT_NUM",
                                            fmt::format("{}", line));
                     additionalData.emplace("INPUT_NAME", pins[pin].name);
-                    additionalData.emplace("INPUT_STATUS",
-                                           fmt::format("{}", value));
                     message =
                         "xyz.openbmc_project.Power.Error.PowerSequencerPGOODFault";
                     return;
@@ -348,7 +392,7 @@
     try
     {
         additionalData.emplace("MFR_STATUS",
-                               fmt::format("{:#010x}", readMFRStatus()));
+                               fmt::format("{:#014x}", readMFRStatus()));
     }
     catch (device_error::ReadFailure& e)
     {
@@ -370,34 +414,38 @@
             {
                 uint8_t vout = pmbusInterface.read(statusVout, Type::Debug);
 
-                // If any bits are on log them, though some are just warnings so
-                // they won't cause errors
                 if (vout)
                 {
+                    // If any bits are on log them, though some are just
+                    // warnings so they won't cause errors
                     log<level::INFO>(
-                        fmt::format("STATUS_VOUT, page: {}, value: {:#04x}",
-                                    page, vout)
+                        fmt::format("{}, value: {:#04x}", statusVout, vout)
                             .c_str());
-                }
 
-                // Log errors if any non-warning bits on
-                if (vout & ~status_vout::WARNING_MASK)
-                {
-                    additionalData.emplace("STATUS_VOUT",
-                                           fmt::format("{:#04x}", vout));
-                    additionalData.emplace("PAGE", fmt::format("{}", page));
-                    if (page < rails.size())
+                    // Log errors if any non-warning bits on
+                    if (vout & ~status_vout::WARNING_MASK)
                     {
-                        additionalData.emplace("RAIL_NAME", rails[page]);
-                    }
+                        additionalData.emplace(
+                            fmt::format("STATUS{}_VOUT", page),
+                            fmt::format("{:#04x}", vout));
 
-                    // Use power supply error if set and 12v rail has failed,
-                    // else use voltage error
-                    message =
-                        ((page == 0) && !powerSupplyError.empty())
-                            ? powerSupplyError
-                            : "xyz.openbmc_project.Power.Error.PowerSequencerVoltageFault";
-                    return;
+                        // Base the callouts on the first vout failure found
+                        if (message.empty())
+                        {
+                            if (page < rails.size())
+                            {
+                                additionalData.emplace("RAIL_NAME",
+                                                       rails[page]);
+                            }
+
+                            // Use power supply error if set and 12v rail has
+                            // failed, else use voltage error
+                            message =
+                                ((page == 0) && !powerSupplyError.empty())
+                                    ? powerSupplyError
+                                    : "xyz.openbmc_project.Power.Error.PowerSequencerVoltageFault";
+                        }
+                    }
                 }
             }
         }
@@ -409,7 +457,7 @@
     return pmbusInterface.read(STATUS_WORD, Type::Debug);
 }
 
-uint32_t UCD90320Monitor::readMFRStatus()
+uint64_t UCD90320Monitor::readMFRStatus()
 {
     const std::string mfrStatus = "mfr_status";
     return pmbusInterface.read(mfrStatus, Type::HwmonDeviceDebug);
diff --git a/phosphor-power-sequencer/src/ucd90320_monitor.hpp b/phosphor-power-sequencer/src/ucd90320_monitor.hpp
index 760b534..7f1d137 100644
--- a/phosphor-power-sequencer/src/ucd90320_monitor.hpp
+++ b/phosphor-power-sequencer/src/ucd90320_monitor.hpp
@@ -122,7 +122,7 @@
      * Reads the mfr_status register
      * @return the register contents
      */
-    uint32_t readMFRStatus();
+    uint64_t readMFRStatus();
 
     /**
      * Reads the status_word register