1abf8da36SMatt Spinler #pragma once 2abf8da36SMatt Spinler 30d0e3554SMatthew Barth #include <fmt/format.h> 40d0e3554SMatthew Barth 50d0e3554SMatthew Barth #include <phosphor-logging/log.hpp> 6abf8da36SMatt Spinler #include <sdbusplus/bus.hpp> 7abf8da36SMatt Spinler #include <sdbusplus/server.hpp> 88fd879fbSWilliam A. Kennington III #include <sdeventplus/clock.hpp> 91cfc2f11SWilliam A. Kennington III #include <sdeventplus/event.hpp> 108fd879fbSWilliam A. Kennington III #include <sdeventplus/utility/timer.hpp> 11abf8da36SMatt Spinler 12177fe986SMatthew Barth #include <chrono> 137c23a049SMatthew Barth #include <utility> 14177fe986SMatthew Barth 15abf8da36SMatt Spinler namespace phosphor 16abf8da36SMatt Spinler { 17abf8da36SMatt Spinler namespace fan 18abf8da36SMatt Spinler { 19abf8da36SMatt Spinler namespace monitor 20abf8da36SMatt Spinler { 21abf8da36SMatt Spinler 22abf8da36SMatt Spinler class Fan; 23abf8da36SMatt Spinler 2478689dd7SMatt Spinler constexpr auto FAN_SENSOR_PATH = "/xyz/openbmc_project/sensors/fan_tach/"; 25abf8da36SMatt Spinler 26abf8da36SMatt Spinler /** 270a9fe160SMatthew Barth * The mode fan monitor will run in: 280a9fe160SMatthew Barth * - init - only do the initialization steps 290a9fe160SMatthew Barth * - monitor - run normal monitoring algorithm 300a9fe160SMatthew Barth */ 310a9fe160SMatthew Barth enum class Mode 320a9fe160SMatthew Barth { 330a9fe160SMatthew Barth init, 340a9fe160SMatthew Barth monitor 350a9fe160SMatthew Barth }; 360a9fe160SMatthew Barth 370a9fe160SMatthew Barth /** 383800ae71SMatthew Barth * The mode that the timer is running in: 393800ae71SMatthew Barth * - func - Transition to functional state timer 403800ae71SMatthew Barth * - nonfunc - Transition to nonfunctional state timer 413800ae71SMatthew Barth */ 423800ae71SMatthew Barth enum class TimerMode 433800ae71SMatthew Barth { 443800ae71SMatthew Barth func, 453800ae71SMatthew Barth nonfunc 463800ae71SMatthew Barth }; 473800ae71SMatthew Barth 483800ae71SMatthew Barth /** 4969f2f48eSJolie Ku * The mode that the method is running in: 5069f2f48eSJolie Ku * - time - Use a percentage based deviation 5169f2f48eSJolie Ku * - count - Run up/down count fault detection 5269f2f48eSJolie Ku */ 5369f2f48eSJolie Ku enum MethodMode 5469f2f48eSJolie Ku { 5569f2f48eSJolie Ku timebased = 0, 5669f2f48eSJolie Ku count 5769f2f48eSJolie Ku }; 5869f2f48eSJolie Ku 5969f2f48eSJolie Ku /** 60abf8da36SMatt Spinler * @class TachSensor 61abf8da36SMatt Spinler * 62abf8da36SMatt Spinler * This class represents the sensor that reads a tach value. 63abf8da36SMatt Spinler * It may also support a Target, which is the property used to 64abf8da36SMatt Spinler * set a speed. Since it doesn't necessarily have a Target, it 65abf8da36SMatt Spinler * won't for sure know if it is running too slow, so it leaves 66abf8da36SMatt Spinler * that determination to other code. 67abf8da36SMatt Spinler * 68abf8da36SMatt Spinler * This class has a parent Fan object that knows about all 69abf8da36SMatt Spinler * sensors for that fan. 70abf8da36SMatt Spinler */ 71abf8da36SMatt Spinler class TachSensor 72abf8da36SMatt Spinler { 73abf8da36SMatt Spinler public: 74abf8da36SMatt Spinler TachSensor() = delete; 75abf8da36SMatt Spinler TachSensor(const TachSensor&) = delete; 76fa0766e3SBrad Bishop // TachSensor is not moveable since the this pointer is used as systemd 77fa0766e3SBrad Bishop // callback context. 78fa0766e3SBrad Bishop TachSensor(TachSensor&&) = delete; 79abf8da36SMatt Spinler TachSensor& operator=(const TachSensor&) = delete; 80fa0766e3SBrad Bishop TachSensor& operator=(TachSensor&&) = delete; 81abf8da36SMatt Spinler ~TachSensor() = default; 82abf8da36SMatt Spinler 83abf8da36SMatt Spinler /** 84abf8da36SMatt Spinler * @brief Constructor 85abf8da36SMatt Spinler * 860a9fe160SMatthew Barth * @param[in] mode - mode of fan monitor 87abf8da36SMatt Spinler * @param[in] bus - the dbus object 88abf8da36SMatt Spinler * @param[in] fan - the parent fan object 89abf8da36SMatt Spinler * @param[in] id - the id of the sensor 90abf8da36SMatt Spinler * @param[in] hasTarget - if the sensor supports 91abf8da36SMatt Spinler * setting the speed 929396bcc3SMatthew Barth * @param[in] funcDelay - Delay to mark functional 9380f271b2SLei YU * @param[in] interface - the interface of the target 948e5d197bSLei YU * @param[in] factor - the factor of the sensor target 958e5d197bSLei YU * @param[in] offset - the offset of the sensor target 9669f2f48eSJolie Ku * @param[in] method - the method of out of range 9769f2f48eSJolie Ku * @param[in] threshold - the threshold of counter method 98abf8da36SMatt Spinler * @param[in] timeout - Normal timeout value to use 99f13b42e2SMatt Spinler * @param[in] errorDelay - Delay in seconds before creating an error 100f13b42e2SMatt Spinler * or std::nullopt if no errors. 101f13b42e2SMatt Spinler * 1021cfc2f11SWilliam A. Kennington III * @param[in] event - Event loop reference 103abf8da36SMatt Spinler */ 104177fe986SMatthew Barth TachSensor(Mode mode, sdbusplus::bus::bus& bus, Fan& fan, 105177fe986SMatthew Barth const std::string& id, bool hasTarget, size_t funcDelay, 106177fe986SMatthew Barth const std::string& interface, double factor, int64_t offset, 10769f2f48eSJolie Ku size_t method, size_t threshold, size_t timeout, 10869f2f48eSJolie Ku const std::optional<size_t>& errorDelay, 109f13b42e2SMatt Spinler const sdeventplus::Event& event); 110abf8da36SMatt Spinler 111abf8da36SMatt Spinler /** 112c8c8ccf3SMatthew Barth * @brief Reads a property from the input message and stores it in value. 113c8c8ccf3SMatthew Barth * T is the value type. 114c8c8ccf3SMatthew Barth * 115c8c8ccf3SMatthew Barth * Note: This can only be called once per message. 116c8c8ccf3SMatthew Barth * 117c8c8ccf3SMatthew Barth * @param[in] msg - the dbus message that contains the data 118c8c8ccf3SMatthew Barth * @param[in] interface - the interface the property is on 119c8c8ccf3SMatthew Barth * @param[in] propertName - the name of the property 120c8c8ccf3SMatthew Barth * @param[out] value - the value to store the property value in 121c8c8ccf3SMatthew Barth */ 122c8c8ccf3SMatthew Barth template <typename T> 123c8c8ccf3SMatthew Barth static void readPropertyFromMessage(sdbusplus::message::message& msg, 124c8c8ccf3SMatthew Barth const std::string& interface, 125c8c8ccf3SMatthew Barth const std::string& propertyName, 126c8c8ccf3SMatthew Barth T& value) 127c8c8ccf3SMatthew Barth { 128c8c8ccf3SMatthew Barth std::string sensor; 129c8c8ccf3SMatthew Barth std::map<std::string, std::variant<T>> data; 130c8c8ccf3SMatthew Barth msg.read(sensor, data); 131c8c8ccf3SMatthew Barth 132c8c8ccf3SMatthew Barth if (sensor.compare(interface) == 0) 133c8c8ccf3SMatthew Barth { 134c8c8ccf3SMatthew Barth auto propertyMap = data.find(propertyName); 135c8c8ccf3SMatthew Barth if (propertyMap != data.end()) 136c8c8ccf3SMatthew Barth { 137c8c8ccf3SMatthew Barth value = std::get<T>(propertyMap->second); 138c8c8ccf3SMatthew Barth } 139c8c8ccf3SMatthew Barth } 140c8c8ccf3SMatthew Barth } 141c8c8ccf3SMatthew Barth 142c8c8ccf3SMatthew Barth /** 143abf8da36SMatt Spinler * @brief Returns the target speed value 144abf8da36SMatt Spinler */ 145f552ea5cSMatthew Barth uint64_t getTarget() const; 146abf8da36SMatt Spinler 147abf8da36SMatt Spinler /** 148abf8da36SMatt Spinler * @brief Returns the input speed value 149abf8da36SMatt Spinler */ 1500891e3b3SMatthew Barth inline double getInput() const 151abf8da36SMatt Spinler { 152abf8da36SMatt Spinler return _tachInput; 153abf8da36SMatt Spinler } 154abf8da36SMatt Spinler 155abf8da36SMatt Spinler /** 156abf8da36SMatt Spinler * @brief Returns true if sensor has a target 157abf8da36SMatt Spinler */ 158abf8da36SMatt Spinler inline bool hasTarget() const 159abf8da36SMatt Spinler { 160abf8da36SMatt Spinler return _hasTarget; 161abf8da36SMatt Spinler } 162abf8da36SMatt Spinler 163abf8da36SMatt Spinler /** 16480f271b2SLei YU * @brief Returns the interface of the sensor target 16580f271b2SLei YU */ 16680f271b2SLei YU inline std::string getInterface() const 16780f271b2SLei YU { 16880f271b2SLei YU return _interface; 16980f271b2SLei YU } 17080f271b2SLei YU 17180f271b2SLei YU /** 1728e5d197bSLei YU * @brief Returns the factor of the sensor target 1738e5d197bSLei YU */ 1745e7298c5SMatthew Barth inline double getFactor() const 1758e5d197bSLei YU { 1768e5d197bSLei YU return _factor; 1778e5d197bSLei YU } 1788e5d197bSLei YU 1798e5d197bSLei YU /** 1808e5d197bSLei YU * @brief Returns the offset of the sensor target 1818e5d197bSLei YU */ 1824eac3cf9SLei YU inline int64_t getOffset() const 1838e5d197bSLei YU { 1848e5d197bSLei YU return _offset; 1858e5d197bSLei YU } 1868e5d197bSLei YU 1878e5d197bSLei YU /** 18869f2f48eSJolie Ku * @brief Returns the method of out of range 18969f2f48eSJolie Ku */ 19069f2f48eSJolie Ku inline size_t getMethod() const 19169f2f48eSJolie Ku { 19269f2f48eSJolie Ku return _method; 19369f2f48eSJolie Ku } 19469f2f48eSJolie Ku 19569f2f48eSJolie Ku /** 19669f2f48eSJolie Ku * @brief Returns the threshold of count method 19769f2f48eSJolie Ku */ 19869f2f48eSJolie Ku inline size_t getThreshold() const 19969f2f48eSJolie Ku { 20069f2f48eSJolie Ku return _threshold; 20169f2f48eSJolie Ku } 20269f2f48eSJolie Ku 20369f2f48eSJolie Ku /** 20469f2f48eSJolie Ku * Set the sensor faulted counter 20569f2f48eSJolie Ku */ 20669f2f48eSJolie Ku void setCounter(bool count); 20769f2f48eSJolie Ku 20869f2f48eSJolie Ku /** 20969f2f48eSJolie Ku * @brief Returns the sensor faulted count 21069f2f48eSJolie Ku */ 21169f2f48eSJolie Ku inline size_t getCounter() const 21269f2f48eSJolie Ku { 21369f2f48eSJolie Ku return _counter; 21469f2f48eSJolie Ku } 21569f2f48eSJolie Ku 21669f2f48eSJolie Ku /** 217abf8da36SMatt Spinler * Returns true if the hardware behind this 218abf8da36SMatt Spinler * sensor is considered working OK/functional. 219abf8da36SMatt Spinler */ 220abf8da36SMatt Spinler inline bool functional() const 221abf8da36SMatt Spinler { 222abf8da36SMatt Spinler return _functional; 223abf8da36SMatt Spinler } 224abf8da36SMatt Spinler 225abf8da36SMatt Spinler /** 226d199dcdfSMatthew Barth * Set the functional status and update inventory to match 227abf8da36SMatt Spinler */ 228d199dcdfSMatthew Barth void setFunctional(bool functional); 229abf8da36SMatt Spinler 230a9406a77SMatt Spinler /** 2316fa181c7SMatt Spinler * @brief Says if the timer is running or not 2326fa181c7SMatt Spinler * 2336fa181c7SMatt Spinler * @return bool - if timer is currently running 234a9406a77SMatt Spinler */ 2356fa181c7SMatt Spinler inline bool timerRunning() 236a9406a77SMatt Spinler { 2378fd879fbSWilliam A. Kennington III return _timer.isEnabled(); 2386fa181c7SMatt Spinler } 2396fa181c7SMatt Spinler 2406fa181c7SMatt Spinler /** 2413800ae71SMatthew Barth * @brief Stops the timer when the given mode differs and starts 2423800ae71SMatthew Barth * the associated timer for the mode given if not already running 2433800ae71SMatthew Barth * 2443800ae71SMatthew Barth * @param[in] mode - mode of timer to start 2456fa181c7SMatt Spinler */ 2463800ae71SMatthew Barth void startTimer(TimerMode mode); 2476fa181c7SMatt Spinler 2486fa181c7SMatt Spinler /** 2496fa181c7SMatt Spinler * @brief Stops the timer 2506fa181c7SMatt Spinler */ 2516fa181c7SMatt Spinler inline void stopTimer() 2526fa181c7SMatt Spinler { 2530d0e3554SMatthew Barth phosphor::logging::log<phosphor::logging::level::INFO>( 2540d0e3554SMatthew Barth fmt::format("Stop running timer on tach sensor {}.", _name) 2550d0e3554SMatthew Barth .c_str()); 2568fd879fbSWilliam A. Kennington III _timer.setEnabled(false); 257a9406a77SMatt Spinler } 258a9406a77SMatt Spinler 259a9406a77SMatt Spinler /** 2603800ae71SMatthew Barth * @brief Return the given timer mode's delay time 2613800ae71SMatthew Barth * 2623800ae71SMatthew Barth * @param[in] mode - mode of timer to get delay time for 263a9406a77SMatt Spinler */ 2643800ae71SMatthew Barth std::chrono::microseconds getDelay(TimerMode mode); 265a9406a77SMatt Spinler 266ce75b511SMatt Spinler /** 267ce75b511SMatt Spinler * Returns the sensor name 268ce75b511SMatt Spinler */ 269ce75b511SMatt Spinler inline const std::string& name() const 270ce75b511SMatt Spinler { 271ce75b511SMatt Spinler return _name; 272ce75b511SMatt Spinler }; 273ce75b511SMatt Spinler 274f13b42e2SMatt Spinler /** 275f13b42e2SMatt Spinler * @brief Says if the error timer is running 276f13b42e2SMatt Spinler * 277f13b42e2SMatt Spinler * @return bool - If the timer is running 278f13b42e2SMatt Spinler */ 279f13b42e2SMatt Spinler bool errorTimerRunning() const 280f13b42e2SMatt Spinler { 281f13b42e2SMatt Spinler if (_errorTimer && _errorTimer->isEnabled()) 282f13b42e2SMatt Spinler { 283f13b42e2SMatt Spinler return true; 284f13b42e2SMatt Spinler } 285f13b42e2SMatt Spinler return false; 286f13b42e2SMatt Spinler } 287f13b42e2SMatt Spinler 2887c23a049SMatthew Barth /** 2897c23a049SMatthew Barth * @brief Get the current allowed range of speeds 2907c23a049SMatthew Barth * 2917c23a049SMatthew Barth * @param[in] deviation - The configured deviation(in percent) allowed 2927c23a049SMatthew Barth * 2937c23a049SMatthew Barth * @return pair - Min/Max range of speeds allowed 2947c23a049SMatthew Barth */ 2957c23a049SMatthew Barth std::pair<uint64_t, uint64_t> getRange(const size_t deviation) const; 2967c23a049SMatthew Barth 297*fcb0dbcbSMatthew Barth /** 298*fcb0dbcbSMatthew Barth * @brief Processes the current state of the sensor 299*fcb0dbcbSMatthew Barth */ 300*fcb0dbcbSMatthew Barth void processState(); 301*fcb0dbcbSMatthew Barth 302*fcb0dbcbSMatthew Barth /** 303*fcb0dbcbSMatthew Barth * @brief Resets the monitoring method of the sensor 304*fcb0dbcbSMatthew Barth */ 305*fcb0dbcbSMatthew Barth void resetMethod(); 306*fcb0dbcbSMatthew Barth 307abf8da36SMatt Spinler private: 308abf8da36SMatt Spinler /** 309ebaae611SMatt Spinler * @brief Returns the match string to use for matching 310ebaae611SMatt Spinler * on a properties changed signal. 311ebaae611SMatt Spinler */ 312ebaae611SMatt Spinler std::string getMatchString(const std::string& interface); 313ebaae611SMatt Spinler 314ebaae611SMatt Spinler /** 315ebaae611SMatt Spinler * @brief Reads the Target property and stores in _tachTarget. 316ebaae611SMatt Spinler * Also calls Fan::tachChanged(). 317ebaae611SMatt Spinler * 318ebaae611SMatt Spinler * @param[in] msg - the dbus message 319ebaae611SMatt Spinler */ 320771659fcSBrad Bishop void handleTargetChange(sdbusplus::message::message& msg); 321ebaae611SMatt Spinler 322ebaae611SMatt Spinler /** 323ebaae611SMatt Spinler * @brief Reads the Value property and stores in _tachInput. 324ebaae611SMatt Spinler * Also calls Fan::tachChanged(). 325ebaae611SMatt Spinler * 326ebaae611SMatt Spinler * @param[in] msg - the dbus message 327ebaae611SMatt Spinler */ 328771659fcSBrad Bishop void handleTachChange(sdbusplus::message::message& msg); 329ebaae611SMatt Spinler 3304d982856SMatthew Barth /** 3314d982856SMatthew Barth * @brief Updates the Functional property in the inventory 3324d982856SMatthew Barth * for this tach sensor based on the value passed in. 3334d982856SMatthew Barth * 3344d982856SMatthew Barth * @param[in] functional - If the Functional property should 3354d982856SMatthew Barth * be set to true or false. 3364d982856SMatthew Barth */ 3374d982856SMatthew Barth void updateInventory(bool functional); 338ebaae611SMatt Spinler 339ebaae611SMatt Spinler /** 340abf8da36SMatt Spinler * @brief the dbus object 341abf8da36SMatt Spinler */ 342abf8da36SMatt Spinler sdbusplus::bus::bus& _bus; 343abf8da36SMatt Spinler 344abf8da36SMatt Spinler /** 345abf8da36SMatt Spinler * @brief Reference to the parent Fan object 346abf8da36SMatt Spinler */ 347abf8da36SMatt Spinler Fan& _fan; 348abf8da36SMatt Spinler 349abf8da36SMatt Spinler /** 350abf8da36SMatt Spinler * @brief The name of the sensor, including the full path 351abf8da36SMatt Spinler * 352abf8da36SMatt Spinler * For example /xyz/openbmc_project/sensors/fan_tach/fan0 353abf8da36SMatt Spinler */ 354abf8da36SMatt Spinler const std::string _name; 355abf8da36SMatt Spinler 356abf8da36SMatt Spinler /** 3574d982856SMatthew Barth * @brief The inventory name of the sensor, including the full path 3584d982856SMatthew Barth */ 3594d982856SMatthew Barth const std::string _invName; 3604d982856SMatthew Barth 3614d982856SMatthew Barth /** 362abf8da36SMatt Spinler * @brief If functional (not too slow). The parent 363abf8da36SMatt Spinler * fan object sets this. 364abf8da36SMatt Spinler */ 365d199dcdfSMatthew Barth bool _functional; 366abf8da36SMatt Spinler 367abf8da36SMatt Spinler /** 368abf8da36SMatt Spinler * @brief If the sensor has a Target property (can set speed) 369abf8da36SMatt Spinler */ 370abf8da36SMatt Spinler const bool _hasTarget; 371abf8da36SMatt Spinler 372abf8da36SMatt Spinler /** 3739396bcc3SMatthew Barth * @brief Amount of time to delay updating to functional 3749396bcc3SMatthew Barth */ 3759396bcc3SMatthew Barth const size_t _funcDelay; 3769396bcc3SMatthew Barth 3779396bcc3SMatthew Barth /** 37880f271b2SLei YU * @brief The interface that the target implements 37980f271b2SLei YU */ 38080f271b2SLei YU const std::string _interface; 38180f271b2SLei YU 38280f271b2SLei YU /** 3838e5d197bSLei YU * @brief The factor of target to get fan rpm 3848e5d197bSLei YU */ 3855e7298c5SMatthew Barth const double _factor; 3868e5d197bSLei YU 3878e5d197bSLei YU /** 3888e5d197bSLei YU * @brief The offset of target to get fan rpm 3898e5d197bSLei YU */ 3904eac3cf9SLei YU const int64_t _offset; 3918e5d197bSLei YU 3928e5d197bSLei YU /** 39369f2f48eSJolie Ku * @brief The method of out of range 39469f2f48eSJolie Ku */ 39569f2f48eSJolie Ku const size_t _method; 39669f2f48eSJolie Ku 39769f2f48eSJolie Ku /** 39869f2f48eSJolie Ku * @brief The threshold for count method 39969f2f48eSJolie Ku */ 40069f2f48eSJolie Ku const size_t _threshold; 40169f2f48eSJolie Ku 40269f2f48eSJolie Ku /** 40369f2f48eSJolie Ku * @brief The counter for count method 40469f2f48eSJolie Ku */ 40569f2f48eSJolie Ku size_t _counter = 0; 40669f2f48eSJolie Ku 40769f2f48eSJolie Ku /** 408abf8da36SMatt Spinler * @brief The input speed, from the Value dbus property 409abf8da36SMatt Spinler */ 4100891e3b3SMatthew Barth double _tachInput = 0; 411abf8da36SMatt Spinler 412abf8da36SMatt Spinler /** 413abf8da36SMatt Spinler * @brief The current target speed, from the Target dbus property 414abf8da36SMatt Spinler * (if applicable) 415abf8da36SMatt Spinler */ 416abf8da36SMatt Spinler uint64_t _tachTarget = 0; 417abf8da36SMatt Spinler 418abf8da36SMatt Spinler /** 419abf8da36SMatt Spinler * @brief The timeout value to use 420abf8da36SMatt Spinler */ 421abf8da36SMatt Spinler const size_t _timeout; 422ebaae611SMatt Spinler 423ebaae611SMatt Spinler /** 4243800ae71SMatthew Barth * @brief Mode that current timer is in 4253800ae71SMatthew Barth */ 4263800ae71SMatthew Barth TimerMode _timerMode; 4273800ae71SMatthew Barth 4283800ae71SMatthew Barth /** 429a9406a77SMatt Spinler * The timer object 430a9406a77SMatt Spinler */ 4318fd879fbSWilliam A. Kennington III sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> _timer; 432a9406a77SMatt Spinler 433a9406a77SMatt Spinler /** 434ebaae611SMatt Spinler * @brief The match object for the Value properties changed signal 435ebaae611SMatt Spinler */ 436ebaae611SMatt Spinler std::unique_ptr<sdbusplus::server::match::match> tachSignal; 437ebaae611SMatt Spinler 438ebaae611SMatt Spinler /** 439ebaae611SMatt Spinler * @brief The match object for the Target properties changed signal 440ebaae611SMatt Spinler */ 441ebaae611SMatt Spinler std::unique_ptr<sdbusplus::server::match::match> targetSignal; 442f13b42e2SMatt Spinler 443f13b42e2SMatt Spinler /** 444f13b42e2SMatt Spinler * @brief The number of seconds to wait between a sensor being set 445f13b42e2SMatt Spinler * to nonfunctional and creating an error for it. 446f13b42e2SMatt Spinler * 447f13b42e2SMatt Spinler * If std::nullopt, no errors will be created. 448f13b42e2SMatt Spinler */ 449f13b42e2SMatt Spinler const std::optional<size_t> _errorDelay; 450f13b42e2SMatt Spinler 451f13b42e2SMatt Spinler /** 452f13b42e2SMatt Spinler * @brief The timer that uses _errorDelay. When it expires an error 453f13b42e2SMatt Spinler * will be created for a faulted fan sensor (rotor). 454f13b42e2SMatt Spinler * 455f13b42e2SMatt Spinler * If _errorDelay is std::nullopt, then this won't be created. 456f13b42e2SMatt Spinler */ 457f13b42e2SMatt Spinler std::unique_ptr< 458f13b42e2SMatt Spinler sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>> 459f13b42e2SMatt Spinler _errorTimer; 460abf8da36SMatt Spinler }; 461abf8da36SMatt Spinler 462177fe986SMatthew Barth } // namespace monitor 463177fe986SMatthew Barth } // namespace fan 464177fe986SMatthew Barth } // namespace phosphor 465