summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog/0001-Customize-phosphor-watchdog-for-Intel-platforms.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog/0001-Customize-phosphor-watchdog-for-Intel-platforms.patch')
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog/0001-Customize-phosphor-watchdog-for-Intel-platforms.patch348
1 files changed, 348 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog/0001-Customize-phosphor-watchdog-for-Intel-platforms.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog/0001-Customize-phosphor-watchdog-for-Intel-platforms.patch
new file mode 100644
index 000000000..48bc4a086
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/watchdog/phosphor-watchdog/0001-Customize-phosphor-watchdog-for-Intel-platforms.patch
@@ -0,0 +1,348 @@
+From a7d1d3770a650df8fe61d594885fcb388ac2ca42 Mon Sep 17 00:00:00 2001
+From: James Feist <james.feist@linux.intel.com>
+Date: Mon, 17 Jun 2019 12:00:58 -0700
+Subject: [PATCH] Customize phosphor-watchdog for Intel platforms
+
+This patch adds various changes to phosphor-watchdog that are
+required for compatibility with Intel platforms.
+
+ 1. Add Redfish messages for watchdog timeout and pre-interrupt
+ 2. Use dbus properties for power control insted of service files
+ 3. Use host status to enable/disable watchdog
+ 4. Set preTimeoutInterruptOccurFlag
+ 5. Assign watchdog cause for correct reset cause reporting
+ 6. Add NMI Pre-Interrupt support for IPMI watchdog timer.
+
+Signed-off-by: James Feist <james.feist@linux.intel.com>
+Signed-off-by: Ren Yu <yux.ren@intel.com>
+Signed-off-by: Yong Li <yong.b.li@linux.intel.com>
+Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
+Signed-off-by: Johnathan Mantey <johnathanx.mantey@intel.com>
+Signed-off-by: Sunita Kumari <sunitax.kumari@intel.com>
+
+%% original patch: 0001-Customize-phosphor-watchdog-for-Intel-platforms.patch
+---
+ src/watchdog.cpp | 229 ++++++++++++++++++++++++++++++++++++++++++++---
+ src/watchdog.hpp | 22 ++++-
+ 2 files changed, 240 insertions(+), 11 deletions(-)
+
+diff --git a/src/watchdog.cpp b/src/watchdog.cpp
+index 7de98ae3e70f..f96faebc7368 100644
+--- a/src/watchdog.cpp
++++ b/src/watchdog.cpp
+@@ -5,8 +5,10 @@
+ #include <phosphor-logging/elog.hpp>
+ #include <phosphor-logging/log.hpp>
+ #include <sdbusplus/exception.hpp>
++#include <systemd/sd-journal.h>
+ #include <string_view>
+ #include <xyz/openbmc_project/Common/error.hpp>
++#include <xyz/openbmc_project/State/Host/server.hpp>
+
+ namespace phosphor
+ {
+@@ -19,10 +21,86 @@ using namespace phosphor::logging;
+ using sdbusplus::exception::SdBusError;
+ using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
+
+-// systemd service to kick start a target.
+-constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
+-constexpr auto SYSTEMD_ROOT = "/org/freedesktop/systemd1";
+-constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
++const static constexpr char* currentHostState = "CurrentHostState";
++const static constexpr char* hostStatusOff =
++ "xyz.openbmc_project.State.Host.HostState.Off";
++
++const static constexpr char* actionDescription = " due to Watchdog timeout";
++const static constexpr char* hardResetDescription = "Hard Reset - System reset";
++const static constexpr char* powerOffDescription =
++ "Power Down - System power down";
++const static constexpr char* powerCycleDescription =
++ "Power Cycle - System power cycle";
++const static constexpr char* timerExpiredDescription = "Timer expired";
++
++const static constexpr char* preInterruptActionNone =
++ "xyz.openbmc_project.State.Watchdog.PreTimeoutInterruptAction.None";
++
++const static constexpr char* preInterruptDescriptionSMI = "SMI";
++const static constexpr char* preInterruptDescriptionNMI = "NMI";
++const static constexpr char* preInterruptDescriptionMI = "Messaging Interrupt";
++
++const static constexpr char* reservedDescription = "Reserved";
++
++const static constexpr char* timerUseDescriptionBIOSFRB2 = "BIOS FRB2";
++const static constexpr char* timerUseDescriptionBIOSPOST = "BIOS/POST";
++const static constexpr char* timerUseDescriptionOSLoad = "OSLoad";
++const static constexpr char* timerUseDescriptionSMSOS = "SMS/OS";
++const static constexpr char* timerUseDescriptionOEM = "OEM";
++
++namespace restart
++{
++static constexpr const char* busName =
++ "xyz.openbmc_project.Control.Host.RestartCause";
++static constexpr const char* path =
++ "/xyz/openbmc_project/control/host0/restart_cause";
++static constexpr const char* interface =
++ "xyz.openbmc_project.Control.Host.RestartCause";
++static constexpr const char* property = "RequestedRestartCause";
++} // namespace restart
++
++// chassis state manager service
++namespace chassis
++{
++static constexpr const char* busName = "xyz.openbmc_project.State.Chassis";
++static constexpr const char* path = "/xyz/openbmc_project/state/chassis0";
++static constexpr const char* interface = "xyz.openbmc_project.State.Chassis";
++static constexpr const char* request = "RequestedPowerTransition";
++} // namespace chassis
++
++namespace host
++{
++static constexpr const char* busName = "xyz.openbmc_project.State.Host";
++static constexpr const char* path = "/xyz/openbmc_project/state/host0";
++static constexpr const char* interface = "xyz.openbmc_project.State.Host";
++static constexpr const char* request = "RequestedHostTransition";
++} // namespace host
++
++namespace nmi
++{
++static constexpr const char* busName = "xyz.openbmc_project.Control.Host.NMI";
++static constexpr const char* path = "/xyz/openbmc_project/control/host0/nmi";
++static constexpr const char* interface = "xyz.openbmc_project.Control.Host.NMI";
++static constexpr const char* request = "NMI";
++
++} // namespace nmi
++
++void Watchdog::powerStateChangedHandler(
++ const std::map<std::string, std::variant<std::string>>& props)
++{
++ const auto iter = props.find(currentHostState);
++ if (iter != props.end())
++ {
++ const std::string* powerState = std::get_if<std::string>(&iter->second);
++ if (powerState && (*powerState == hostStatusOff))
++ {
++ if (timerEnabled())
++ {
++ enabled(false);
++ }
++ }
++ }
++}
+
+ void Watchdog::resetTimeRemaining(bool enableWatchdog)
+ {
+@@ -108,13 +186,111 @@ uint64_t Watchdog::interval(uint64_t value)
+ // Optional callback function on timer expiration
+ void Watchdog::timeOutHandler()
+ {
++ PreTimeoutInterruptAction preTimeoutInterruptAction = preTimeoutInterrupt();
++ std::string preInterruptActionMessageArgs{};
++
+ Action action = expireAction();
++ std::string actionMessageArgs{};
++
++ expiredTimerUse(currentTimerUse());
++
++ TimerUse timeUser = expiredTimerUse();
++ std::string timeUserMessage{};
++
+ if (!this->enabled())
+ {
+ action = fallback->action;
+ }
+
+- expiredTimerUse(currentTimerUse());
++ switch (timeUser)
++ {
++ case Watchdog::TimerUse::BIOSFRB2:
++ timeUserMessage = timerUseDescriptionBIOSFRB2;
++ break;
++ case Watchdog::TimerUse::BIOSPOST:
++ timeUserMessage = timerUseDescriptionBIOSPOST;
++ break;
++ case Watchdog::TimerUse::OSLoad:
++ timeUserMessage = timerUseDescriptionOSLoad;
++ break;
++ case Watchdog::TimerUse::SMSOS:
++ timeUserMessage = timerUseDescriptionSMSOS;
++ break;
++ case Watchdog::TimerUse::OEM:
++ timeUserMessage = timerUseDescriptionOEM;
++ break;
++ default:
++ timeUserMessage = reservedDescription;
++ break;
++ }
++
++ switch (action)
++ {
++ case Watchdog::Action::HardReset:
++ actionMessageArgs = std::string(hardResetDescription) +
++ std::string(actionDescription);
++ break;
++ case Watchdog::Action::PowerOff:
++ actionMessageArgs = std::string(powerOffDescription) +
++ std::string(actionDescription);
++ break;
++ case Watchdog::Action::PowerCycle:
++ actionMessageArgs = std::string(powerCycleDescription) +
++ std::string(actionDescription);
++ break;
++ case Watchdog::Action::None:
++ actionMessageArgs = timerExpiredDescription;
++ break;
++ default:
++ actionMessageArgs = reservedDescription;
++ break;
++ }
++
++ // Log into redfish event log
++ sd_journal_send("MESSAGE=IPMIWatchdog: Timed out ACTION=%s",
++ convertForMessage(action).c_str(), "PRIORITY=%i", LOG_INFO,
++ "REDFISH_MESSAGE_ID=%s", "OpenBMC.0.1.IPMIWatchdog",
++ "REDFISH_MESSAGE_ARGS=%s. timer use: %s",
++ actionMessageArgs.c_str(), timeUserMessage.c_str(), NULL);
++
++ switch (preTimeoutInterruptAction)
++ {
++ case Watchdog::PreTimeoutInterruptAction::SMI:
++ preInterruptActionMessageArgs = preInterruptDescriptionSMI;
++ break;
++ case Watchdog::PreTimeoutInterruptAction::NMI:
++ preInterruptActionMessageArgs = preInterruptDescriptionNMI;
++ break;
++ case Watchdog::PreTimeoutInterruptAction::MI:
++ preInterruptActionMessageArgs = preInterruptDescriptionMI;
++ break;
++ default:
++ preInterruptActionMessageArgs = reservedDescription;
++ break;
++ }
++
++ if (preInterruptActionNone != convertForMessage(preTimeoutInterruptAction))
++ {
++ preTimeoutInterruptOccurFlag(true);
++
++ sd_journal_send("MESSAGE=IPMIWatchdog: Pre Timed out Interrupt=%s",
++ convertForMessage(preTimeoutInterruptAction).c_str(),
++ "PRIORITY=%i", LOG_INFO, "REDFISH_MESSAGE_ID=%s",
++ "OpenBMC.0.1.IPMIWatchdog",
++ "REDFISH_MESSAGE_ARGS=Timer interrupt - %s due to "
++ "Watchdog timeout. timer use: %s",
++ preInterruptActionMessageArgs.c_str(),
++ timeUserMessage.c_str(), NULL);
++
++ if (preTimeoutInterruptAction ==
++ Watchdog::PreTimeoutInterruptAction::NMI)
++ {
++ sdbusplus::message::message preTimeoutInterruptHandler;
++ preTimeoutInterruptHandler = bus.new_method_call(
++ nmi::busName, nmi::path, nmi::interface, nmi::request);
++ bus.call_noreply(preTimeoutInterruptHandler);
++ }
++ }
+
+ auto target = actionTargetMap.find(action);
+ if (target == actionTargetMap.end())
+@@ -147,12 +323,45 @@ void Watchdog::timeOutHandler()
+
+ try
+ {
+- auto method = bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_ROOT,
+- SYSTEMD_INTERFACE, "StartUnit");
+- method.append(target->second);
+- method.append("replace");
++ sdbusplus::message::message method;
++ if (action == Watchdog::Action::HardReset)
++ {
++ auto method = bus.new_method_call(
++ restart::busName, restart::path,
++ "org.freedesktop.DBus.Properties", "Set");
++ method.append(
++ restart::interface, restart::property,
++ std::variant<std::string>("xyz.openbmc_project.State.Host."
++ "RestartCause.WatchdogTimer"));
++ bus.call_noreply(method);
+
+- bus.call_noreply(method);
++ method = bus.new_method_call(host::busName, host::path,
++ "org.freedesktop.DBus.Properties",
++ "Set");
++ method.append(host::interface, host::request,
++ std::variant<std::string>(target->second));
++ bus.call_noreply(method);
++ }
++ else
++ {
++ if (action == Watchdog::Action::PowerCycle)
++ {
++ auto method = bus.new_method_call(
++ restart::busName, restart::path,
++ "org.freedesktop.DBus.Properties", "Set");
++ method.append(restart::interface, restart::property,
++ std::variant<std::string>(
++ "xyz.openbmc_project.State.Host."
++ "RestartCause.WatchdogTimer"));
++ bus.call_noreply(method);
++ }
++ method = bus.new_method_call(chassis::busName, chassis::path,
++ "org.freedesktop.DBus.Properties",
++ "Set");
++ method.append(chassis::interface, chassis::request,
++ std::variant<std::string>(target->second));
++ bus.call_noreply(method);
++ }
+ }
+ catch (const SdBusError& e)
+ {
+diff --git a/src/watchdog.hpp b/src/watchdog.hpp
+index 736e71f68fcc..79158f192f40 100644
+--- a/src/watchdog.hpp
++++ b/src/watchdog.hpp
+@@ -73,7 +73,17 @@ class Watchdog : public WatchdogInherits
+ bus(bus), actionTargetMap(std::move(actionTargetMap)),
+ fallback(std::move(fallback)), minInterval(minInterval),
+ timer(event, std::bind(&Watchdog::timeOutHandler, this)),
+- objPath(objPath)
++ objPath(objPath), powerStateChangedSignal(
++ bus,
++ sdbusplus::bus::match::rules::propertiesChanged(
++ "/xyz/openbmc_project/state/host0",
++ "xyz.openbmc_project.State.Host"),
++ [this](sdbusplus::message::message& msg) {
++ std::string objectName;
++ std::map<std::string, std::variant<std::string>> props;
++ msg.read(objectName, props);
++ powerStateChangedHandler(props);
++ })
+ {
+ // Use default if passed in otherwise just use default that comes
+ // with object
+@@ -90,6 +100,12 @@ class Watchdog : public WatchdogInherits
+ tryFallbackOrDisable();
+ }
+
++ /** @brief Disable watchdog when power status change meet
++ * the specific requirement
++ */
++ void powerStateChangedHandler(
++ const std::map<std::string, std::variant<std::string>>& props);
++
+ /** @brief Resets the TimeRemaining to the configured Interval
+ * Optionally enables the watchdog.
+ *
+@@ -178,6 +194,10 @@ class Watchdog : public WatchdogInherits
+ /** @brief Contained timer object */
+ sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> timer;
+
++ /** @brief Optional Callback handler when power status change meet
++ * the specific requirement */
++ sdbusplus::bus::match_t powerStateChangedSignal;
++
+ /** @brief Optional Callback handler on timer expirartion */
+ void timeOutHandler();
+
+--
+2.17.1
+