| Patrick Venture | 8f6c515 | 2018-09-11 17:45:33 -0700 | [diff] [blame] | 1 | #include "watchdog.hpp" | 
|  | 2 |  | 
| Ofer Yehielli | c35135d | 2019-06-14 11:30:25 -0700 | [diff] [blame] | 3 | #include <algorithm> | 
| Vishwanatha Subbanna | d7a3f13 | 2017-05-29 19:39:08 +0530 | [diff] [blame] | 4 | #include <chrono> | 
| William A. Kennington III | 7036c56 | 2018-10-03 23:36:16 -0700 | [diff] [blame] | 5 | #include <phosphor-logging/elog.hpp> | 
| Vishwanatha Subbanna | d7a3f13 | 2017-05-29 19:39:08 +0530 | [diff] [blame] | 6 | #include <phosphor-logging/log.hpp> | 
| William A. Kennington III | 7036c56 | 2018-10-03 23:36:16 -0700 | [diff] [blame] | 7 | #include <sdbusplus/exception.hpp> | 
|  | 8 | #include <xyz/openbmc_project/Common/error.hpp> | 
|  | 9 |  | 
| Vishwanatha Subbanna | d7a3f13 | 2017-05-29 19:39:08 +0530 | [diff] [blame] | 10 | namespace phosphor | 
|  | 11 | { | 
|  | 12 | namespace watchdog | 
|  | 13 | { | 
|  | 14 | using namespace std::chrono; | 
|  | 15 | using namespace std::chrono_literals; | 
|  | 16 | using namespace phosphor::logging; | 
|  | 17 |  | 
| William A. Kennington III | 7036c56 | 2018-10-03 23:36:16 -0700 | [diff] [blame] | 18 | using sdbusplus::exception::SdBusError; | 
|  | 19 | using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; | 
|  | 20 |  | 
| Vishwanatha Subbanna | 3473d70 | 2017-05-30 16:38:50 +0530 | [diff] [blame] | 21 | // systemd service to kick start a target. | 
| Patrick Venture | 8f6c515 | 2018-09-11 17:45:33 -0700 | [diff] [blame] | 22 | constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1"; | 
|  | 23 | constexpr auto SYSTEMD_ROOT = "/org/freedesktop/systemd1"; | 
|  | 24 | constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager"; | 
| Vishwanatha Subbanna | 3473d70 | 2017-05-30 16:38:50 +0530 | [diff] [blame] | 25 |  | 
| William A. Kennington III | 1726df6 | 2018-04-23 10:28:28 -0700 | [diff] [blame] | 26 | void Watchdog::resetTimeRemaining(bool enableWatchdog) | 
|  | 27 | { | 
|  | 28 | timeRemaining(interval()); | 
|  | 29 | if (enableWatchdog) | 
|  | 30 | { | 
|  | 31 | enabled(true); | 
|  | 32 | } | 
|  | 33 | } | 
|  | 34 |  | 
| Vishwanatha Subbanna | d7a3f13 | 2017-05-29 19:39:08 +0530 | [diff] [blame] | 35 | // Enable or disable watchdog | 
|  | 36 | bool Watchdog::enabled(bool value) | 
|  | 37 | { | 
| William A. Kennington III | 825f498 | 2018-02-27 19:10:56 -0800 | [diff] [blame] | 38 | if (!value) | 
| Vishwanatha Subbanna | d7a3f13 | 2017-05-29 19:39:08 +0530 | [diff] [blame] | 39 | { | 
| William A. Kennington III | d133108 | 2018-02-27 18:47:05 -0800 | [diff] [blame] | 40 | // Make sure we accurately reflect our enabled state to the | 
|  | 41 | // tryFallbackOrDisable() call | 
|  | 42 | WatchdogInherits::enabled(value); | 
|  | 43 |  | 
|  | 44 | // Attempt to fallback or disable our timer if needed | 
|  | 45 | tryFallbackOrDisable(); | 
| Vishwanatha Subbanna | d7a3f13 | 2017-05-29 19:39:08 +0530 | [diff] [blame] | 46 |  | 
| William A. Kennington III | 825f498 | 2018-02-27 19:10:56 -0800 | [diff] [blame] | 47 | return false; | 
| Vishwanatha Subbanna | d7a3f13 | 2017-05-29 19:39:08 +0530 | [diff] [blame] | 48 | } | 
| William A. Kennington III | 825f498 | 2018-02-27 19:10:56 -0800 | [diff] [blame] | 49 | else if (!this->enabled()) | 
|  | 50 | { | 
| William A. Kennington III | f505fc0 | 2018-09-12 18:30:09 -0700 | [diff] [blame] | 51 | auto interval_ms = this->interval(); | 
|  | 52 | timer.restart(milliseconds(interval_ms)); | 
| William A. Kennington III | 825f498 | 2018-02-27 19:10:56 -0800 | [diff] [blame] | 53 | log<level::INFO>("watchdog: enabled and started", | 
| William A. Kennington III | f505fc0 | 2018-09-12 18:30:09 -0700 | [diff] [blame] | 54 | entry("INTERVAL=%llu", interval_ms)); | 
| William A. Kennington III | 825f498 | 2018-02-27 19:10:56 -0800 | [diff] [blame] | 55 | } | 
|  | 56 |  | 
| Vishwanatha Subbanna | d7a3f13 | 2017-05-29 19:39:08 +0530 | [diff] [blame] | 57 | return WatchdogInherits::enabled(value); | 
|  | 58 | } | 
|  | 59 |  | 
|  | 60 | // Get the remaining time before timer expires. | 
|  | 61 | // If the timer is disabled, returns 0 | 
|  | 62 | uint64_t Watchdog::timeRemaining() const | 
|  | 63 | { | 
| William A. Kennington III | 1c9515f | 2018-02-27 18:54:36 -0800 | [diff] [blame] | 64 | // timer may have already expired and disabled | 
| William A. Kennington III | f505fc0 | 2018-09-12 18:30:09 -0700 | [diff] [blame] | 65 | if (!timerEnabled()) | 
| Vishwanatha Subbanna | d7a3f13 | 2017-05-29 19:39:08 +0530 | [diff] [blame] | 66 | { | 
| William A. Kennington III | f505fc0 | 2018-09-12 18:30:09 -0700 | [diff] [blame] | 67 | return 0; | 
| Vishwanatha Subbanna | d7a3f13 | 2017-05-29 19:39:08 +0530 | [diff] [blame] | 68 | } | 
| William A. Kennington III | f505fc0 | 2018-09-12 18:30:09 -0700 | [diff] [blame] | 69 |  | 
|  | 70 | return duration_cast<milliseconds>(timer.getRemaining()).count(); | 
| Vishwanatha Subbanna | d7a3f13 | 2017-05-29 19:39:08 +0530 | [diff] [blame] | 71 | } | 
|  | 72 |  | 
|  | 73 | // Reset the timer to a new expiration value | 
|  | 74 | uint64_t Watchdog::timeRemaining(uint64_t value) | 
|  | 75 | { | 
| William A. Kennington III | 0650a3f | 2018-03-01 10:53:25 -0800 | [diff] [blame] | 76 | if (!timerEnabled()) | 
| Vishwanatha Subbanna | d7a3f13 | 2017-05-29 19:39:08 +0530 | [diff] [blame] | 77 | { | 
| William A. Kennington III | 5e3f877 | 2018-02-27 18:59:58 -0800 | [diff] [blame] | 78 | // We don't need to update the timer because it is off | 
|  | 79 | return 0; | 
| Vishwanatha Subbanna | d7a3f13 | 2017-05-29 19:39:08 +0530 | [diff] [blame] | 80 | } | 
| William A. Kennington III | 5e3f877 | 2018-02-27 18:59:58 -0800 | [diff] [blame] | 81 |  | 
| William A. Kennington III | d133108 | 2018-02-27 18:47:05 -0800 | [diff] [blame] | 82 | if (!this->enabled()) | 
|  | 83 | { | 
|  | 84 | // Having a timer but not displaying an enabled value means we | 
|  | 85 | // are inside of the fallback | 
|  | 86 | value = fallback->interval; | 
|  | 87 | } | 
|  | 88 |  | 
| William A. Kennington III | 5e3f877 | 2018-02-27 18:59:58 -0800 | [diff] [blame] | 89 | // Update new expiration | 
| William A. Kennington III | f505fc0 | 2018-09-12 18:30:09 -0700 | [diff] [blame] | 90 | timer.setRemaining(milliseconds(value)); | 
| William A. Kennington III | 5e3f877 | 2018-02-27 18:59:58 -0800 | [diff] [blame] | 91 |  | 
|  | 92 | // Update Base class data. | 
|  | 93 | return WatchdogInherits::timeRemaining(value); | 
| Vishwanatha Subbanna | d7a3f13 | 2017-05-29 19:39:08 +0530 | [diff] [blame] | 94 | } | 
|  | 95 |  | 
| Ofer Yehielli | c35135d | 2019-06-14 11:30:25 -0700 | [diff] [blame] | 96 | // Set value of Interval | 
|  | 97 | uint64_t Watchdog::interval(uint64_t value) | 
|  | 98 | { | 
|  | 99 | return WatchdogInherits::interval(std::max(value, minInterval)); | 
|  | 100 | } | 
|  | 101 |  | 
| Vishwanatha Subbanna | 8c5a229 | 2017-05-30 15:34:23 +0530 | [diff] [blame] | 102 | // Optional callback function on timer expiration | 
|  | 103 | void Watchdog::timeOutHandler() | 
|  | 104 | { | 
| William A. Kennington III | d133108 | 2018-02-27 18:47:05 -0800 | [diff] [blame] | 105 | Action action = expireAction(); | 
|  | 106 | if (!this->enabled()) | 
|  | 107 | { | 
|  | 108 | action = fallback->action; | 
|  | 109 | } | 
| Vishwanatha Subbanna | 3473d70 | 2017-05-30 16:38:50 +0530 | [diff] [blame] | 110 |  | 
| William A. Kennington III | 47a9ec4 | 2019-04-18 15:42:16 -0700 | [diff] [blame] | 111 | expiredTimerUse(currentTimerUse()); | 
| Yong Li | 50ae4b1 | 2019-03-20 17:08:24 +0800 | [diff] [blame] | 112 |  | 
| William A. Kennington III | 3bb2f40 | 2018-09-13 00:35:47 -0700 | [diff] [blame] | 113 | auto target = actionTargetMap.find(action); | 
|  | 114 | if (target == actionTargetMap.end()) | 
| William A. Kennington III | 1232a15 | 2018-02-02 15:57:34 -0800 | [diff] [blame] | 115 | { | 
|  | 116 | log<level::INFO>("watchdog: Timed out with no target", | 
| William A. Kennington III | 47a9ec4 | 2019-04-18 15:42:16 -0700 | [diff] [blame] | 117 | entry("ACTION=%s", convertForMessage(action).c_str()), | 
|  | 118 | entry("TIMER_USE=%s", | 
|  | 119 | convertForMessage(expiredTimerUse()).c_str())); | 
| William A. Kennington III | 825f498 | 2018-02-27 19:10:56 -0800 | [diff] [blame] | 120 | } | 
|  | 121 | else | 
|  | 122 | { | 
| William A. Kennington III | 47a9ec4 | 2019-04-18 15:42:16 -0700 | [diff] [blame] | 123 | log<level::INFO>( | 
|  | 124 | "watchdog: Timed out", | 
|  | 125 | entry("ACTION=%s", convertForMessage(action).c_str()), | 
|  | 126 | entry("TIMER_USE=%s", convertForMessage(expiredTimerUse()).c_str()), | 
|  | 127 | entry("TARGET=%s", target->second.c_str())); | 
| William A. Kennington III | 7036c56 | 2018-10-03 23:36:16 -0700 | [diff] [blame] | 128 |  | 
|  | 129 | try | 
|  | 130 | { | 
|  | 131 | auto method = bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_ROOT, | 
|  | 132 | SYSTEMD_INTERFACE, "StartUnit"); | 
|  | 133 | method.append(target->second); | 
|  | 134 | method.append("replace"); | 
|  | 135 |  | 
|  | 136 | bus.call_noreply(method); | 
|  | 137 | } | 
|  | 138 | catch (const SdBusError& e) | 
|  | 139 | { | 
|  | 140 | log<level::ERR>("watchdog: Failed to start unit", | 
|  | 141 | entry("TARGET=%s", target->second.c_str()), | 
|  | 142 | entry("ERROR=%s", e.what())); | 
|  | 143 | commit<InternalFailure>(); | 
|  | 144 | } | 
| Vishwanatha Subbanna | 3473d70 | 2017-05-30 16:38:50 +0530 | [diff] [blame] | 145 | } | 
| William A. Kennington III | 1232a15 | 2018-02-02 15:57:34 -0800 | [diff] [blame] | 146 |  | 
| William A. Kennington III | d133108 | 2018-02-27 18:47:05 -0800 | [diff] [blame] | 147 | tryFallbackOrDisable(); | 
| William A. Kennington III | 825f498 | 2018-02-27 19:10:56 -0800 | [diff] [blame] | 148 | } | 
| William A. Kennington III | 1232a15 | 2018-02-02 15:57:34 -0800 | [diff] [blame] | 149 |  | 
| William A. Kennington III | d133108 | 2018-02-27 18:47:05 -0800 | [diff] [blame] | 150 | void Watchdog::tryFallbackOrDisable() | 
| William A. Kennington III | 825f498 | 2018-02-27 19:10:56 -0800 | [diff] [blame] | 151 | { | 
| William A. Kennington III | d133108 | 2018-02-27 18:47:05 -0800 | [diff] [blame] | 152 | // We only re-arm the watchdog if we were already enabled and have | 
|  | 153 | // a possible fallback | 
| William A. Kennington III | 2235219 | 2018-02-27 18:51:44 -0800 | [diff] [blame] | 154 | if (fallback && (fallback->always || this->enabled())) | 
| William A. Kennington III | d133108 | 2018-02-27 18:47:05 -0800 | [diff] [blame] | 155 | { | 
|  | 156 | auto interval_ms = fallback->interval; | 
| William A. Kennington III | f505fc0 | 2018-09-12 18:30:09 -0700 | [diff] [blame] | 157 | timer.restart(milliseconds(interval_ms)); | 
| William A. Kennington III | d133108 | 2018-02-27 18:47:05 -0800 | [diff] [blame] | 158 | log<level::INFO>("watchdog: falling back", | 
| Patrick Venture | 8f6c515 | 2018-09-11 17:45:33 -0700 | [diff] [blame] | 159 | entry("INTERVAL=%llu", interval_ms)); | 
| William A. Kennington III | d133108 | 2018-02-27 18:47:05 -0800 | [diff] [blame] | 160 | } | 
|  | 161 | else if (timerEnabled()) | 
| William A. Kennington III | 825f498 | 2018-02-27 19:10:56 -0800 | [diff] [blame] | 162 | { | 
| William A. Kennington III | f505fc0 | 2018-09-12 18:30:09 -0700 | [diff] [blame] | 163 | timer.setEnabled(false); | 
| William A. Kennington III | 825f498 | 2018-02-27 19:10:56 -0800 | [diff] [blame] | 164 |  | 
|  | 165 | log<level::INFO>("watchdog: disabled"); | 
|  | 166 | } | 
|  | 167 |  | 
|  | 168 | // Make sure we accurately reflect our enabled state to the | 
|  | 169 | // dbus interface. | 
|  | 170 | WatchdogInherits::enabled(false); | 
| Vishwanatha Subbanna | 8c5a229 | 2017-05-30 15:34:23 +0530 | [diff] [blame] | 171 | } | 
|  | 172 |  | 
| Vishwanatha Subbanna | d7a3f13 | 2017-05-29 19:39:08 +0530 | [diff] [blame] | 173 | } // namespace watchdog | 
| Patrick Venture | 8f6c515 | 2018-09-11 17:45:33 -0700 | [diff] [blame] | 174 | } // namespace phosphor |