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