xref: /openbmc/dbus-sensors/src/Thresholds.hpp (revision 18b6186e531ae37dd22b634c6530f793528473f4)
1e73bd0a1SAndrew Jeffery #pragma once
2e73bd0a1SAndrew Jeffery 
3e73bd0a1SAndrew Jeffery #include "Utils.hpp"
4e73bd0a1SAndrew Jeffery 
51f978631SEd Tanous #include <boost/asio/io_context.hpp>
6e73bd0a1SAndrew Jeffery #include <boost/asio/steady_timer.hpp>
7*18b6186eSEd Tanous #include <sdbusplus/asio/connection.hpp>
8e73bd0a1SAndrew Jeffery 
9*18b6186eSEd Tanous #include <array>
10*18b6186eSEd Tanous #include <cstddef>
11*18b6186eSEd Tanous #include <cstdint>
12*18b6186eSEd Tanous #include <limits>
13e73bd0a1SAndrew Jeffery #include <list>
14e73bd0a1SAndrew Jeffery #include <memory>
15e73bd0a1SAndrew Jeffery #include <string>
16e73bd0a1SAndrew Jeffery #include <utility>
17e73bd0a1SAndrew Jeffery #include <vector>
18e73bd0a1SAndrew Jeffery 
19e73bd0a1SAndrew Jeffery struct Sensor;
20e73bd0a1SAndrew Jeffery namespace thresholds
21e73bd0a1SAndrew Jeffery {
22e73bd0a1SAndrew Jeffery enum class Level
23e73bd0a1SAndrew Jeffery {
24e73bd0a1SAndrew Jeffery     WARNING,
25e73bd0a1SAndrew Jeffery     CRITICAL,
26e73bd0a1SAndrew Jeffery     PERFORMANCELOSS,
27e73bd0a1SAndrew Jeffery     SOFTSHUTDOWN,
28e73bd0a1SAndrew Jeffery     HARDSHUTDOWN,
29e73bd0a1SAndrew Jeffery     ERROR
30e73bd0a1SAndrew Jeffery };
31e73bd0a1SAndrew Jeffery enum class Direction
32e73bd0a1SAndrew Jeffery {
33e73bd0a1SAndrew Jeffery     HIGH,
34e73bd0a1SAndrew Jeffery     LOW,
35e73bd0a1SAndrew Jeffery     ERROR
36e73bd0a1SAndrew Jeffery };
37e73bd0a1SAndrew Jeffery struct Threshold
38e73bd0a1SAndrew Jeffery {
Thresholdthresholds::Threshold39e73bd0a1SAndrew Jeffery     Threshold(
40e73bd0a1SAndrew Jeffery         const Level& lev, const Direction& dir, const double& val,
41e73bd0a1SAndrew Jeffery         const double hysteresis = std::numeric_limits<double>::quiet_NaN(),
42e73bd0a1SAndrew Jeffery         bool write = true) :
432aaf7175SPatrick Williams         level(lev), direction(dir), value(val), hysteresis(hysteresis),
442aaf7175SPatrick Williams         writeable(write)
45e73bd0a1SAndrew Jeffery     {}
46e73bd0a1SAndrew Jeffery     Level level;
47e73bd0a1SAndrew Jeffery     Direction direction;
48e73bd0a1SAndrew Jeffery     double value;
49e73bd0a1SAndrew Jeffery     double hysteresis;
50e73bd0a1SAndrew Jeffery     bool writeable;
51e73bd0a1SAndrew Jeffery 
operator ==thresholds::Threshold52e73bd0a1SAndrew Jeffery     bool operator==(const Threshold& rhs) const
53e73bd0a1SAndrew Jeffery     {
54e73bd0a1SAndrew Jeffery         return (level == rhs.level && direction == rhs.direction &&
55e73bd0a1SAndrew Jeffery                 value == rhs.value);
56e73bd0a1SAndrew Jeffery     }
57e73bd0a1SAndrew Jeffery };
58e73bd0a1SAndrew Jeffery 
59e73bd0a1SAndrew Jeffery void assertThresholds(Sensor* sensor, double assertValue,
60e73bd0a1SAndrew Jeffery                       thresholds::Level level, thresholds::Direction direction,
61e73bd0a1SAndrew Jeffery                       bool assert);
62e73bd0a1SAndrew Jeffery 
63e73bd0a1SAndrew Jeffery struct TimerUsed
64e73bd0a1SAndrew Jeffery {
65e73bd0a1SAndrew Jeffery     bool used;
66e73bd0a1SAndrew Jeffery     Level level;
67e73bd0a1SAndrew Jeffery     Direction direction;
68e73bd0a1SAndrew Jeffery     bool assert;
69e73bd0a1SAndrew Jeffery };
70e73bd0a1SAndrew Jeffery 
71e73bd0a1SAndrew Jeffery using TimerPair = std::pair<struct TimerUsed, boost::asio::steady_timer>;
72e73bd0a1SAndrew Jeffery 
73e73bd0a1SAndrew Jeffery struct ThresholdTimer
74e73bd0a1SAndrew Jeffery {
ThresholdTimerthresholds::ThresholdTimer751f978631SEd Tanous     explicit ThresholdTimer(boost::asio::io_context& ioService) : io(ioService)
76e73bd0a1SAndrew Jeffery     {}
77e73bd0a1SAndrew Jeffery 
hasActiveTimerthresholds::ThresholdTimer78e73bd0a1SAndrew Jeffery     bool hasActiveTimer(const Threshold& threshold, bool assert)
79e73bd0a1SAndrew Jeffery     {
80e73bd0a1SAndrew Jeffery         for (TimerPair& timer : timers)
81e73bd0a1SAndrew Jeffery         {
82e73bd0a1SAndrew Jeffery             if (timer.first.used)
83e73bd0a1SAndrew Jeffery             {
84e73bd0a1SAndrew Jeffery                 if ((timer.first.level == threshold.level) &&
85e73bd0a1SAndrew Jeffery                     (timer.first.direction == threshold.direction) &&
86e73bd0a1SAndrew Jeffery                     (timer.first.assert == assert))
87e73bd0a1SAndrew Jeffery                 {
88e73bd0a1SAndrew Jeffery                     return true;
89e73bd0a1SAndrew Jeffery                 }
90e73bd0a1SAndrew Jeffery             }
91e73bd0a1SAndrew Jeffery         }
92e73bd0a1SAndrew Jeffery         return false;
93e73bd0a1SAndrew Jeffery     }
94e73bd0a1SAndrew Jeffery 
stopTimerthresholds::ThresholdTimer95e73bd0a1SAndrew Jeffery     void stopTimer(const Threshold& threshold, bool assert)
96e73bd0a1SAndrew Jeffery     {
97e73bd0a1SAndrew Jeffery         struct TimerUsed timerUsed = {};
98e73bd0a1SAndrew Jeffery         for (TimerPair& timer : timers)
99e73bd0a1SAndrew Jeffery         {
100e73bd0a1SAndrew Jeffery             timerUsed = timer.first;
101e73bd0a1SAndrew Jeffery             if (timerUsed.used)
102e73bd0a1SAndrew Jeffery             {
103e73bd0a1SAndrew Jeffery                 if ((timerUsed.level == threshold.level) &&
104e73bd0a1SAndrew Jeffery                     (timerUsed.direction == threshold.direction) &&
105e73bd0a1SAndrew Jeffery                     (timerUsed.assert == assert))
106e73bd0a1SAndrew Jeffery                 {
107e73bd0a1SAndrew Jeffery                     timer.second.cancel();
108e73bd0a1SAndrew Jeffery                 }
109e73bd0a1SAndrew Jeffery             }
110e73bd0a1SAndrew Jeffery         }
111e73bd0a1SAndrew Jeffery     }
112e73bd0a1SAndrew Jeffery 
113e73bd0a1SAndrew Jeffery     void startTimer(const std::weak_ptr<Sensor>& weakSensor,
114e73bd0a1SAndrew Jeffery                     const Threshold& threshold, bool assert,
115e73bd0a1SAndrew Jeffery                     double assertValue);
116e73bd0a1SAndrew Jeffery 
1171f978631SEd Tanous     boost::asio::io_context& io;
118e73bd0a1SAndrew Jeffery     std::list<TimerPair> timers;
119e73bd0a1SAndrew Jeffery };
120e73bd0a1SAndrew Jeffery 
121e73bd0a1SAndrew Jeffery bool parseThresholdsFromConfig(
122e73bd0a1SAndrew Jeffery     const SensorData& sensorData,
123e73bd0a1SAndrew Jeffery     std::vector<thresholds::Threshold>& thresholdVector,
124e73bd0a1SAndrew Jeffery     const std::string* matchLabel = nullptr, const int* sensorIndex = nullptr);
125e73bd0a1SAndrew Jeffery 
126a327923dSChris Sides // Sensors touched by parseThresholdFromAttr() are forcibly updated with given
127a327923dSChris Sides // parameters, so callers are encouraged to specify a sane hysteresis value for
128a327923dSChris Sides // their HW. For reference, the hysteresis fomula used in Sensor.hpp is:
129a327923dSChris Sides //  hysteresis.trigger = (max_val - min_val) * 0.01
130e73bd0a1SAndrew Jeffery bool parseThresholdsFromAttr(
131e73bd0a1SAndrew Jeffery     std::vector<thresholds::Threshold>& thresholdVector,
132e73bd0a1SAndrew Jeffery     const std::string& inputPath, const double& scaleFactor,
133a327923dSChris Sides     const double& offset = 0,
134a327923dSChris Sides     const double& hysteresis = std::numeric_limits<double>::quiet_NaN());
135e73bd0a1SAndrew Jeffery 
136e73bd0a1SAndrew Jeffery struct ThresholdDefinition
137e73bd0a1SAndrew Jeffery {
138e73bd0a1SAndrew Jeffery     Level level;
139e73bd0a1SAndrew Jeffery     uint8_t sevOrder;
140e73bd0a1SAndrew Jeffery     const char* levelName;
141e73bd0a1SAndrew Jeffery };
142e73bd0a1SAndrew Jeffery 
143e73bd0a1SAndrew Jeffery constexpr static std::array<thresholds::ThresholdDefinition, 5> thresProp = {
144e73bd0a1SAndrew Jeffery     {{Level::WARNING, 0, "Warning"},
145e73bd0a1SAndrew Jeffery      {Level::CRITICAL, 1, "Critical"},
146e73bd0a1SAndrew Jeffery      {Level::PERFORMANCELOSS, 2, "PerformanceLoss"},
147e73bd0a1SAndrew Jeffery      {Level::SOFTSHUTDOWN, 3, "SoftShutdown"},
148e73bd0a1SAndrew Jeffery      {Level::HARDSHUTDOWN, 4, "HardShutdown"}}};
149e73bd0a1SAndrew Jeffery 
150e73bd0a1SAndrew Jeffery std::string getInterface(Level level);
151e73bd0a1SAndrew Jeffery 
152e73bd0a1SAndrew Jeffery void persistThreshold(const std::string& path, const std::string& baseInterface,
153e73bd0a1SAndrew Jeffery                       const thresholds::Threshold& threshold,
154e73bd0a1SAndrew Jeffery                       std::shared_ptr<sdbusplus::asio::connection>& conn,
155e73bd0a1SAndrew Jeffery                       size_t thresholdCount, const std::string& label);
156e73bd0a1SAndrew Jeffery 
157e73bd0a1SAndrew Jeffery void updateThresholds(Sensor* sensor);
158e73bd0a1SAndrew Jeffery // returns false if a critical threshold has been crossed, true otherwise
159e73bd0a1SAndrew Jeffery bool checkThresholds(Sensor* sensor);
160e73bd0a1SAndrew Jeffery void checkThresholdsPowerDelay(const std::weak_ptr<Sensor>& weakSensor,
161e73bd0a1SAndrew Jeffery                                ThresholdTimer& thresholdTimer);
162e73bd0a1SAndrew Jeffery 
163e73bd0a1SAndrew Jeffery } // namespace thresholds
164