1abf8da36SMatt Spinler #pragma once 2abf8da36SMatt Spinler 3abf8da36SMatt Spinler #include <sdbusplus/bus.hpp> 4abf8da36SMatt Spinler #include <sdbusplus/server.hpp> 58fd879fbSWilliam A. Kennington III #include <sdeventplus/clock.hpp> 61cfc2f11SWilliam A. Kennington III #include <sdeventplus/event.hpp> 78fd879fbSWilliam A. Kennington III #include <sdeventplus/utility/timer.hpp> 8abf8da36SMatt Spinler 9177fe986SMatthew Barth #include <chrono> 10177fe986SMatthew Barth 11abf8da36SMatt Spinler namespace phosphor 12abf8da36SMatt Spinler { 13abf8da36SMatt Spinler namespace fan 14abf8da36SMatt Spinler { 15abf8da36SMatt Spinler namespace monitor 16abf8da36SMatt Spinler { 17abf8da36SMatt Spinler 18abf8da36SMatt Spinler class Fan; 19abf8da36SMatt Spinler 2078689dd7SMatt Spinler constexpr auto FAN_SENSOR_PATH = "/xyz/openbmc_project/sensors/fan_tach/"; 21abf8da36SMatt Spinler 22abf8da36SMatt Spinler /** 230a9fe160SMatthew Barth * The mode fan monitor will run in: 240a9fe160SMatthew Barth * - init - only do the initialization steps 250a9fe160SMatthew Barth * - monitor - run normal monitoring algorithm 260a9fe160SMatthew Barth */ 270a9fe160SMatthew Barth enum class Mode 280a9fe160SMatthew Barth { 290a9fe160SMatthew Barth init, 300a9fe160SMatthew Barth monitor 310a9fe160SMatthew Barth }; 320a9fe160SMatthew Barth 330a9fe160SMatthew Barth /** 343800ae71SMatthew Barth * The mode that the timer is running in: 353800ae71SMatthew Barth * - func - Transition to functional state timer 363800ae71SMatthew Barth * - nonfunc - Transition to nonfunctional state timer 373800ae71SMatthew Barth */ 383800ae71SMatthew Barth enum class TimerMode 393800ae71SMatthew Barth { 403800ae71SMatthew Barth func, 413800ae71SMatthew Barth nonfunc 423800ae71SMatthew Barth }; 433800ae71SMatthew Barth 443800ae71SMatthew Barth /** 45*69f2f48eSJolie Ku * The mode that the method is running in: 46*69f2f48eSJolie Ku * - time - Use a percentage based deviation 47*69f2f48eSJolie Ku * - count - Run up/down count fault detection 48*69f2f48eSJolie Ku */ 49*69f2f48eSJolie Ku enum MethodMode 50*69f2f48eSJolie Ku { 51*69f2f48eSJolie Ku timebased = 0, 52*69f2f48eSJolie Ku count 53*69f2f48eSJolie Ku }; 54*69f2f48eSJolie Ku 55*69f2f48eSJolie Ku /** 56abf8da36SMatt Spinler * @class TachSensor 57abf8da36SMatt Spinler * 58abf8da36SMatt Spinler * This class represents the sensor that reads a tach value. 59abf8da36SMatt Spinler * It may also support a Target, which is the property used to 60abf8da36SMatt Spinler * set a speed. Since it doesn't necessarily have a Target, it 61abf8da36SMatt Spinler * won't for sure know if it is running too slow, so it leaves 62abf8da36SMatt Spinler * that determination to other code. 63abf8da36SMatt Spinler * 64abf8da36SMatt Spinler * This class has a parent Fan object that knows about all 65abf8da36SMatt Spinler * sensors for that fan. 66abf8da36SMatt Spinler */ 67abf8da36SMatt Spinler class TachSensor 68abf8da36SMatt Spinler { 69abf8da36SMatt Spinler public: 70abf8da36SMatt Spinler TachSensor() = delete; 71abf8da36SMatt Spinler TachSensor(const TachSensor&) = delete; 72fa0766e3SBrad Bishop // TachSensor is not moveable since the this pointer is used as systemd 73fa0766e3SBrad Bishop // callback context. 74fa0766e3SBrad Bishop TachSensor(TachSensor&&) = delete; 75abf8da36SMatt Spinler TachSensor& operator=(const TachSensor&) = delete; 76fa0766e3SBrad Bishop TachSensor& operator=(TachSensor&&) = delete; 77abf8da36SMatt Spinler ~TachSensor() = default; 78abf8da36SMatt Spinler 79abf8da36SMatt Spinler /** 80abf8da36SMatt Spinler * @brief Constructor 81abf8da36SMatt Spinler * 820a9fe160SMatthew Barth * @param[in] mode - mode of fan monitor 83abf8da36SMatt Spinler * @param[in] bus - the dbus object 84abf8da36SMatt Spinler * @param[in] fan - the parent fan object 85abf8da36SMatt Spinler * @param[in] id - the id of the sensor 86abf8da36SMatt Spinler * @param[in] hasTarget - if the sensor supports 87abf8da36SMatt Spinler * setting the speed 889396bcc3SMatthew Barth * @param[in] funcDelay - Delay to mark functional 8980f271b2SLei YU * @param[in] interface - the interface of the target 908e5d197bSLei YU * @param[in] factor - the factor of the sensor target 918e5d197bSLei YU * @param[in] offset - the offset of the sensor target 92*69f2f48eSJolie Ku * @param[in] method - the method of out of range 93*69f2f48eSJolie Ku * @param[in] threshold - the threshold of counter method 94abf8da36SMatt Spinler * @param[in] timeout - Normal timeout value to use 95f13b42e2SMatt Spinler * @param[in] errorDelay - Delay in seconds before creating an error 96f13b42e2SMatt Spinler * or std::nullopt if no errors. 97f13b42e2SMatt Spinler * 981cfc2f11SWilliam A. Kennington III * @param[in] event - Event loop reference 99abf8da36SMatt Spinler */ 100177fe986SMatthew Barth TachSensor(Mode mode, sdbusplus::bus::bus& bus, Fan& fan, 101177fe986SMatthew Barth const std::string& id, bool hasTarget, size_t funcDelay, 102177fe986SMatthew Barth const std::string& interface, double factor, int64_t offset, 103*69f2f48eSJolie Ku size_t method, size_t threshold, size_t timeout, 104*69f2f48eSJolie Ku const std::optional<size_t>& errorDelay, 105f13b42e2SMatt Spinler const sdeventplus::Event& event); 106abf8da36SMatt Spinler 107abf8da36SMatt Spinler /** 108abf8da36SMatt Spinler * @brief Returns the target speed value 109abf8da36SMatt Spinler */ 110f552ea5cSMatthew Barth uint64_t getTarget() const; 111abf8da36SMatt Spinler 112abf8da36SMatt Spinler /** 113abf8da36SMatt Spinler * @brief Returns the input speed value 114abf8da36SMatt Spinler */ 1150891e3b3SMatthew Barth inline double getInput() const 116abf8da36SMatt Spinler { 117abf8da36SMatt Spinler return _tachInput; 118abf8da36SMatt Spinler } 119abf8da36SMatt Spinler 120abf8da36SMatt Spinler /** 121abf8da36SMatt Spinler * @brief Returns true if sensor has a target 122abf8da36SMatt Spinler */ 123abf8da36SMatt Spinler inline bool hasTarget() const 124abf8da36SMatt Spinler { 125abf8da36SMatt Spinler return _hasTarget; 126abf8da36SMatt Spinler } 127abf8da36SMatt Spinler 128abf8da36SMatt Spinler /** 12980f271b2SLei YU * @brief Returns the interface of the sensor target 13080f271b2SLei YU */ 13180f271b2SLei YU inline std::string getInterface() const 13280f271b2SLei YU { 13380f271b2SLei YU return _interface; 13480f271b2SLei YU } 13580f271b2SLei YU 13680f271b2SLei YU /** 1378e5d197bSLei YU * @brief Returns the factor of the sensor target 1388e5d197bSLei YU */ 1395e7298c5SMatthew Barth inline double getFactor() const 1408e5d197bSLei YU { 1418e5d197bSLei YU return _factor; 1428e5d197bSLei YU } 1438e5d197bSLei YU 1448e5d197bSLei YU /** 1458e5d197bSLei YU * @brief Returns the offset of the sensor target 1468e5d197bSLei YU */ 1474eac3cf9SLei YU inline int64_t getOffset() const 1488e5d197bSLei YU { 1498e5d197bSLei YU return _offset; 1508e5d197bSLei YU } 1518e5d197bSLei YU 1528e5d197bSLei YU /** 153*69f2f48eSJolie Ku * @brief Returns the method of out of range 154*69f2f48eSJolie Ku */ 155*69f2f48eSJolie Ku inline size_t getMethod() const 156*69f2f48eSJolie Ku { 157*69f2f48eSJolie Ku return _method; 158*69f2f48eSJolie Ku } 159*69f2f48eSJolie Ku 160*69f2f48eSJolie Ku /** 161*69f2f48eSJolie Ku * @brief Returns the threshold of count method 162*69f2f48eSJolie Ku */ 163*69f2f48eSJolie Ku inline size_t getThreshold() const 164*69f2f48eSJolie Ku { 165*69f2f48eSJolie Ku return _threshold; 166*69f2f48eSJolie Ku } 167*69f2f48eSJolie Ku 168*69f2f48eSJolie Ku /** 169*69f2f48eSJolie Ku * Set the sensor faulted counter 170*69f2f48eSJolie Ku */ 171*69f2f48eSJolie Ku void setCounter(bool count); 172*69f2f48eSJolie Ku 173*69f2f48eSJolie Ku /** 174*69f2f48eSJolie Ku * @brief Returns the sensor faulted count 175*69f2f48eSJolie Ku */ 176*69f2f48eSJolie Ku inline size_t getCounter() const 177*69f2f48eSJolie Ku { 178*69f2f48eSJolie Ku return _counter; 179*69f2f48eSJolie Ku } 180*69f2f48eSJolie Ku 181*69f2f48eSJolie Ku /** 182abf8da36SMatt Spinler * Returns true if the hardware behind this 183abf8da36SMatt Spinler * sensor is considered working OK/functional. 184abf8da36SMatt Spinler */ 185abf8da36SMatt Spinler inline bool functional() const 186abf8da36SMatt Spinler { 187abf8da36SMatt Spinler return _functional; 188abf8da36SMatt Spinler } 189abf8da36SMatt Spinler 190abf8da36SMatt Spinler /** 191d199dcdfSMatthew Barth * Set the functional status and update inventory to match 192abf8da36SMatt Spinler */ 193d199dcdfSMatthew Barth void setFunctional(bool functional); 194abf8da36SMatt Spinler 195a9406a77SMatt Spinler /** 1966fa181c7SMatt Spinler * @brief Says if the timer is running or not 1976fa181c7SMatt Spinler * 1986fa181c7SMatt Spinler * @return bool - if timer is currently running 199a9406a77SMatt Spinler */ 2006fa181c7SMatt Spinler inline bool timerRunning() 201a9406a77SMatt Spinler { 2028fd879fbSWilliam A. Kennington III return _timer.isEnabled(); 2036fa181c7SMatt Spinler } 2046fa181c7SMatt Spinler 2056fa181c7SMatt Spinler /** 2063800ae71SMatthew Barth * @brief Stops the timer when the given mode differs and starts 2073800ae71SMatthew Barth * the associated timer for the mode given if not already running 2083800ae71SMatthew Barth * 2093800ae71SMatthew Barth * @param[in] mode - mode of timer to start 2106fa181c7SMatt Spinler */ 2113800ae71SMatthew Barth void startTimer(TimerMode mode); 2126fa181c7SMatt Spinler 2136fa181c7SMatt Spinler /** 2146fa181c7SMatt Spinler * @brief Stops the timer 2156fa181c7SMatt Spinler */ 2166fa181c7SMatt Spinler inline void stopTimer() 2176fa181c7SMatt Spinler { 2188fd879fbSWilliam A. Kennington III _timer.setEnabled(false); 219a9406a77SMatt Spinler } 220a9406a77SMatt Spinler 221a9406a77SMatt Spinler /** 2223800ae71SMatthew Barth * @brief Return the given timer mode's delay time 2233800ae71SMatthew Barth * 2243800ae71SMatthew Barth * @param[in] mode - mode of timer to get delay time for 225a9406a77SMatt Spinler */ 2263800ae71SMatthew Barth std::chrono::microseconds getDelay(TimerMode mode); 227a9406a77SMatt Spinler 228ce75b511SMatt Spinler /** 229ce75b511SMatt Spinler * Returns the sensor name 230ce75b511SMatt Spinler */ 231ce75b511SMatt Spinler inline const std::string& name() const 232ce75b511SMatt Spinler { 233ce75b511SMatt Spinler return _name; 234ce75b511SMatt Spinler }; 235ce75b511SMatt Spinler 236f13b42e2SMatt Spinler /** 237f13b42e2SMatt Spinler * @brief Says if the error timer is running 238f13b42e2SMatt Spinler * 239f13b42e2SMatt Spinler * @return bool - If the timer is running 240f13b42e2SMatt Spinler */ 241f13b42e2SMatt Spinler bool errorTimerRunning() const 242f13b42e2SMatt Spinler { 243f13b42e2SMatt Spinler if (_errorTimer && _errorTimer->isEnabled()) 244f13b42e2SMatt Spinler { 245f13b42e2SMatt Spinler return true; 246f13b42e2SMatt Spinler } 247f13b42e2SMatt Spinler return false; 248f13b42e2SMatt Spinler } 249f13b42e2SMatt Spinler 250abf8da36SMatt Spinler private: 251abf8da36SMatt Spinler /** 252ebaae611SMatt Spinler * @brief Returns the match string to use for matching 253ebaae611SMatt Spinler * on a properties changed signal. 254ebaae611SMatt Spinler */ 255ebaae611SMatt Spinler std::string getMatchString(const std::string& interface); 256ebaae611SMatt Spinler 257ebaae611SMatt Spinler /** 258ebaae611SMatt Spinler * @brief Reads the Target property and stores in _tachTarget. 259ebaae611SMatt Spinler * Also calls Fan::tachChanged(). 260ebaae611SMatt Spinler * 261ebaae611SMatt Spinler * @param[in] msg - the dbus message 262ebaae611SMatt Spinler */ 263771659fcSBrad Bishop void handleTargetChange(sdbusplus::message::message& msg); 264ebaae611SMatt Spinler 265ebaae611SMatt Spinler /** 266ebaae611SMatt Spinler * @brief Reads the Value property and stores in _tachInput. 267ebaae611SMatt Spinler * Also calls Fan::tachChanged(). 268ebaae611SMatt Spinler * 269ebaae611SMatt Spinler * @param[in] msg - the dbus message 270ebaae611SMatt Spinler */ 271771659fcSBrad Bishop void handleTachChange(sdbusplus::message::message& msg); 272ebaae611SMatt Spinler 2734d982856SMatthew Barth /** 2744d982856SMatthew Barth * @brief Updates the Functional property in the inventory 2754d982856SMatthew Barth * for this tach sensor based on the value passed in. 2764d982856SMatthew Barth * 2774d982856SMatthew Barth * @param[in] functional - If the Functional property should 2784d982856SMatthew Barth * be set to true or false. 2794d982856SMatthew Barth */ 2804d982856SMatthew Barth void updateInventory(bool functional); 281ebaae611SMatt Spinler 282ebaae611SMatt Spinler /** 283abf8da36SMatt Spinler * @brief the dbus object 284abf8da36SMatt Spinler */ 285abf8da36SMatt Spinler sdbusplus::bus::bus& _bus; 286abf8da36SMatt Spinler 287abf8da36SMatt Spinler /** 288abf8da36SMatt Spinler * @brief Reference to the parent Fan object 289abf8da36SMatt Spinler */ 290abf8da36SMatt Spinler Fan& _fan; 291abf8da36SMatt Spinler 292abf8da36SMatt Spinler /** 293abf8da36SMatt Spinler * @brief The name of the sensor, including the full path 294abf8da36SMatt Spinler * 295abf8da36SMatt Spinler * For example /xyz/openbmc_project/sensors/fan_tach/fan0 296abf8da36SMatt Spinler */ 297abf8da36SMatt Spinler const std::string _name; 298abf8da36SMatt Spinler 299abf8da36SMatt Spinler /** 3004d982856SMatthew Barth * @brief The inventory name of the sensor, including the full path 3014d982856SMatthew Barth */ 3024d982856SMatthew Barth const std::string _invName; 3034d982856SMatthew Barth 3044d982856SMatthew Barth /** 305abf8da36SMatt Spinler * @brief If functional (not too slow). The parent 306abf8da36SMatt Spinler * fan object sets this. 307abf8da36SMatt Spinler */ 308d199dcdfSMatthew Barth bool _functional; 309abf8da36SMatt Spinler 310abf8da36SMatt Spinler /** 311abf8da36SMatt Spinler * @brief If the sensor has a Target property (can set speed) 312abf8da36SMatt Spinler */ 313abf8da36SMatt Spinler const bool _hasTarget; 314abf8da36SMatt Spinler 315abf8da36SMatt Spinler /** 3169396bcc3SMatthew Barth * @brief Amount of time to delay updating to functional 3179396bcc3SMatthew Barth */ 3189396bcc3SMatthew Barth const size_t _funcDelay; 3199396bcc3SMatthew Barth 3209396bcc3SMatthew Barth /** 32180f271b2SLei YU * @brief The interface that the target implements 32280f271b2SLei YU */ 32380f271b2SLei YU const std::string _interface; 32480f271b2SLei YU 32580f271b2SLei YU /** 3268e5d197bSLei YU * @brief The factor of target to get fan rpm 3278e5d197bSLei YU */ 3285e7298c5SMatthew Barth const double _factor; 3298e5d197bSLei YU 3308e5d197bSLei YU /** 3318e5d197bSLei YU * @brief The offset of target to get fan rpm 3328e5d197bSLei YU */ 3334eac3cf9SLei YU const int64_t _offset; 3348e5d197bSLei YU 3358e5d197bSLei YU /** 336*69f2f48eSJolie Ku * @brief The method of out of range 337*69f2f48eSJolie Ku */ 338*69f2f48eSJolie Ku const size_t _method; 339*69f2f48eSJolie Ku 340*69f2f48eSJolie Ku /** 341*69f2f48eSJolie Ku * @brief The threshold for count method 342*69f2f48eSJolie Ku */ 343*69f2f48eSJolie Ku const size_t _threshold; 344*69f2f48eSJolie Ku 345*69f2f48eSJolie Ku /** 346*69f2f48eSJolie Ku * @brief The counter for count method 347*69f2f48eSJolie Ku */ 348*69f2f48eSJolie Ku size_t _counter = 0; 349*69f2f48eSJolie Ku 350*69f2f48eSJolie Ku /** 351abf8da36SMatt Spinler * @brief The input speed, from the Value dbus property 352abf8da36SMatt Spinler */ 3530891e3b3SMatthew Barth double _tachInput = 0; 354abf8da36SMatt Spinler 355abf8da36SMatt Spinler /** 356abf8da36SMatt Spinler * @brief The current target speed, from the Target dbus property 357abf8da36SMatt Spinler * (if applicable) 358abf8da36SMatt Spinler */ 359abf8da36SMatt Spinler uint64_t _tachTarget = 0; 360abf8da36SMatt Spinler 361abf8da36SMatt Spinler /** 362abf8da36SMatt Spinler * @brief The timeout value to use 363abf8da36SMatt Spinler */ 364abf8da36SMatt Spinler const size_t _timeout; 365ebaae611SMatt Spinler 366ebaae611SMatt Spinler /** 3673800ae71SMatthew Barth * @brief Mode that current timer is in 3683800ae71SMatthew Barth */ 3693800ae71SMatthew Barth TimerMode _timerMode; 3703800ae71SMatthew Barth 3713800ae71SMatthew Barth /** 372a9406a77SMatt Spinler * The timer object 373a9406a77SMatt Spinler */ 3748fd879fbSWilliam A. Kennington III sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> _timer; 375a9406a77SMatt Spinler 376a9406a77SMatt Spinler /** 377ebaae611SMatt Spinler * @brief The match object for the Value properties changed signal 378ebaae611SMatt Spinler */ 379ebaae611SMatt Spinler std::unique_ptr<sdbusplus::server::match::match> tachSignal; 380ebaae611SMatt Spinler 381ebaae611SMatt Spinler /** 382ebaae611SMatt Spinler * @brief The match object for the Target properties changed signal 383ebaae611SMatt Spinler */ 384ebaae611SMatt Spinler std::unique_ptr<sdbusplus::server::match::match> targetSignal; 385f13b42e2SMatt Spinler 386f13b42e2SMatt Spinler /** 387f13b42e2SMatt Spinler * @brief The number of seconds to wait between a sensor being set 388f13b42e2SMatt Spinler * to nonfunctional and creating an error for it. 389f13b42e2SMatt Spinler * 390f13b42e2SMatt Spinler * If std::nullopt, no errors will be created. 391f13b42e2SMatt Spinler */ 392f13b42e2SMatt Spinler const std::optional<size_t> _errorDelay; 393f13b42e2SMatt Spinler 394f13b42e2SMatt Spinler /** 395f13b42e2SMatt Spinler * @brief The timer that uses _errorDelay. When it expires an error 396f13b42e2SMatt Spinler * will be created for a faulted fan sensor (rotor). 397f13b42e2SMatt Spinler * 398f13b42e2SMatt Spinler * If _errorDelay is std::nullopt, then this won't be created. 399f13b42e2SMatt Spinler */ 400f13b42e2SMatt Spinler std::unique_ptr< 401f13b42e2SMatt Spinler sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>> 402f13b42e2SMatt Spinler _errorTimer; 403abf8da36SMatt Spinler }; 404abf8da36SMatt Spinler 405177fe986SMatthew Barth } // namespace monitor 406177fe986SMatthew Barth } // namespace fan 407177fe986SMatthew Barth } // namespace phosphor 408