blob: 76a800dab94f0731a539859d85029e85d5ec021c [file] [log] [blame]
Matt Spinlerabf8da32017-04-27 14:08:45 -05001#pragma once
2
Matt Spinlerabf8da32017-04-27 14:08:45 -05003#include <sdbusplus/bus.hpp>
4#include <sdbusplus/server.hpp>
William A. Kennington III8fd879f2018-10-30 19:49:29 -07005#include <sdeventplus/clock.hpp>
William A. Kennington III1cfc2f12018-10-19 17:29:46 -07006#include <sdeventplus/event.hpp>
William A. Kennington III8fd879f2018-10-30 19:49:29 -07007#include <sdeventplus/utility/timer.hpp>
Matt Spinlerabf8da32017-04-27 14:08:45 -05008
Matthew Barth177fe982020-05-26 11:05:19 -05009#include <chrono>
10
Matt Spinlerabf8da32017-04-27 14:08:45 -050011namespace phosphor
12{
13namespace fan
14{
15namespace monitor
16{
17
18class Fan;
19
Matt Spinler78689dd2017-09-28 10:12:07 -050020constexpr auto FAN_SENSOR_PATH = "/xyz/openbmc_project/sensors/fan_tach/";
Matt Spinlerabf8da32017-04-27 14:08:45 -050021
22/**
Matthew Barth0a9fe162018-01-26 12:53:15 -060023 * The mode fan monitor will run in:
24 * - init - only do the initialization steps
25 * - monitor - run normal monitoring algorithm
26 */
27enum class Mode
28{
29 init,
30 monitor
31};
32
33/**
Matthew Barth3800ae72018-02-19 16:08:04 -060034 * The mode that the timer is running in:
35 * - func - Transition to functional state timer
36 * - nonfunc - Transition to nonfunctional state timer
37 */
38enum class TimerMode
39{
40 func,
41 nonfunc
42};
43
44/**
Jolie Ku69f2f482020-10-21 09:59:43 +080045 * The mode that the method is running in:
46 * - time - Use a percentage based deviation
47 * - count - Run up/down count fault detection
48 */
49enum MethodMode
50{
51 timebased = 0,
52 count
53};
54
55/**
Matt Spinlerabf8da32017-04-27 14:08:45 -050056 * @class TachSensor
57 *
58 * This class represents the sensor that reads a tach value.
59 * It may also support a Target, which is the property used to
60 * set a speed. Since it doesn't necessarily have a Target, it
61 * won't for sure know if it is running too slow, so it leaves
62 * that determination to other code.
63 *
64 * This class has a parent Fan object that knows about all
65 * sensors for that fan.
66 */
67class TachSensor
68{
Matthew Barth177fe982020-05-26 11:05:19 -050069 public:
70 TachSensor() = delete;
71 TachSensor(const TachSensor&) = delete;
72 // TachSensor is not moveable since the this pointer is used as systemd
73 // callback context.
74 TachSensor(TachSensor&&) = delete;
75 TachSensor& operator=(const TachSensor&) = delete;
76 TachSensor& operator=(TachSensor&&) = delete;
77 ~TachSensor() = default;
Matt Spinlerabf8da32017-04-27 14:08:45 -050078
Matthew Barth177fe982020-05-26 11:05:19 -050079 /**
80 * @brief Constructor
81 *
82 * @param[in] mode - mode of fan monitor
83 * @param[in] bus - the dbus object
84 * @param[in] fan - the parent fan object
85 * @param[in] id - the id of the sensor
86 * @param[in] hasTarget - if the sensor supports
87 * setting the speed
88 * @param[in] funcDelay - Delay to mark functional
89 * @param[in] interface - the interface of the target
90 * @param[in] factor - the factor of the sensor target
91 * @param[in] offset - the offset of the sensor target
Jolie Ku69f2f482020-10-21 09:59:43 +080092 * @param[in] method - the method of out of range
93 * @param[in] threshold - the threshold of counter method
Matthew Barth177fe982020-05-26 11:05:19 -050094 * @param[in] timeout - Normal timeout value to use
Matt Spinlerf13b42e2020-10-26 15:29:49 -050095 * @param[in] errorDelay - Delay in seconds before creating an error
96 * or std::nullopt if no errors.
97 *
Matthew Barth177fe982020-05-26 11:05:19 -050098 * @param[in] event - Event loop reference
99 */
100 TachSensor(Mode mode, sdbusplus::bus::bus& bus, Fan& fan,
101 const std::string& id, bool hasTarget, size_t funcDelay,
102 const std::string& interface, double factor, int64_t offset,
Jolie Ku69f2f482020-10-21 09:59:43 +0800103 size_t method, size_t threshold, size_t timeout,
104 const std::optional<size_t>& errorDelay,
Matt Spinlerf13b42e2020-10-26 15:29:49 -0500105 const sdeventplus::Event& event);
Matt Spinlerabf8da32017-04-27 14:08:45 -0500106
Matthew Barth177fe982020-05-26 11:05:19 -0500107 /**
108 * @brief Returns the target speed value
109 */
110 uint64_t getTarget() const;
Matt Spinlerabf8da32017-04-27 14:08:45 -0500111
Matthew Barth177fe982020-05-26 11:05:19 -0500112 /**
113 * @brief Returns the input speed value
114 */
Matthew Barth0891e3b2020-08-13 12:00:23 -0500115 inline double getInput() const
Matthew Barth177fe982020-05-26 11:05:19 -0500116 {
117 return _tachInput;
118 }
Matt Spinlerabf8da32017-04-27 14:08:45 -0500119
Matthew Barth177fe982020-05-26 11:05:19 -0500120 /**
121 * @brief Returns true if sensor has a target
122 */
123 inline bool hasTarget() const
124 {
125 return _hasTarget;
126 }
Matt Spinlerabf8da32017-04-27 14:08:45 -0500127
Matthew Barth177fe982020-05-26 11:05:19 -0500128 /**
129 * @brief Returns the interface of the sensor target
130 */
131 inline std::string getInterface() const
132 {
133 return _interface;
134 }
Matt Spinlerabf8da32017-04-27 14:08:45 -0500135
Matthew Barth177fe982020-05-26 11:05:19 -0500136 /**
137 * @brief Returns the factor of the sensor target
138 */
139 inline double getFactor() const
140 {
141 return _factor;
142 }
Lei YU80f271b2018-01-31 15:24:46 +0800143
Matthew Barth177fe982020-05-26 11:05:19 -0500144 /**
145 * @brief Returns the offset of the sensor target
146 */
147 inline int64_t getOffset() const
148 {
149 return _offset;
150 }
Lei YU8e5d1972018-01-26 17:14:00 +0800151
Matthew Barth177fe982020-05-26 11:05:19 -0500152 /**
Jolie Ku69f2f482020-10-21 09:59:43 +0800153 * @brief Returns the method of out of range
154 */
155 inline size_t getMethod() const
156 {
157 return _method;
158 }
159
160 /**
161 * @brief Returns the threshold of count method
162 */
163 inline size_t getThreshold() const
164 {
165 return _threshold;
166 }
167
168 /**
169 * Set the sensor faulted counter
170 */
171 void setCounter(bool count);
172
173 /**
174 * @brief Returns the sensor faulted count
175 */
176 inline size_t getCounter() const
177 {
178 return _counter;
179 }
180
181 /**
Matthew Barth177fe982020-05-26 11:05:19 -0500182 * Returns true if the hardware behind this
183 * sensor is considered working OK/functional.
184 */
185 inline bool functional() const
186 {
187 return _functional;
188 }
Lei YU8e5d1972018-01-26 17:14:00 +0800189
Matthew Barth177fe982020-05-26 11:05:19 -0500190 /**
191 * Set the functional status and update inventory to match
192 */
193 void setFunctional(bool functional);
Matt Spinlerabf8da32017-04-27 14:08:45 -0500194
Matthew Barth177fe982020-05-26 11:05:19 -0500195 /**
196 * @brief Says if the timer is running or not
197 *
198 * @return bool - if timer is currently running
199 */
200 inline bool timerRunning()
201 {
202 return _timer.isEnabled();
203 }
Matt Spinlerabf8da32017-04-27 14:08:45 -0500204
Matthew Barth177fe982020-05-26 11:05:19 -0500205 /**
206 * @brief Stops the timer when the given mode differs and starts
207 * the associated timer for the mode given if not already running
208 *
209 * @param[in] mode - mode of timer to start
210 */
211 void startTimer(TimerMode mode);
Matt Spinler6fa181c2017-09-27 16:24:45 -0500212
Matthew Barth177fe982020-05-26 11:05:19 -0500213 /**
214 * @brief Stops the timer
215 */
216 inline void stopTimer()
217 {
218 _timer.setEnabled(false);
219 }
Matt Spinler6fa181c2017-09-27 16:24:45 -0500220
Matthew Barth177fe982020-05-26 11:05:19 -0500221 /**
222 * @brief Return the given timer mode's delay time
223 *
224 * @param[in] mode - mode of timer to get delay time for
225 */
226 std::chrono::microseconds getDelay(TimerMode mode);
Matt Spinlera9406a72017-04-27 14:29:24 -0500227
Matthew Barth177fe982020-05-26 11:05:19 -0500228 /**
229 * Returns the sensor name
230 */
231 inline const std::string& name() const
232 {
233 return _name;
234 };
Matt Spinlera9406a72017-04-27 14:29:24 -0500235
Matt Spinlerf13b42e2020-10-26 15:29:49 -0500236 /**
237 * @brief Says if the error timer is running
238 *
239 * @return bool - If the timer is running
240 */
241 bool errorTimerRunning() const
242 {
243 if (_errorTimer && _errorTimer->isEnabled())
244 {
245 return true;
246 }
247 return false;
248 }
249
Matthew Barth177fe982020-05-26 11:05:19 -0500250 private:
251 /**
252 * @brief Returns the match string to use for matching
253 * on a properties changed signal.
254 */
255 std::string getMatchString(const std::string& interface);
Matt Spinlerce75b512017-07-26 15:10:48 -0500256
Matthew Barth177fe982020-05-26 11:05:19 -0500257 /**
258 * @brief Reads the Target property and stores in _tachTarget.
259 * Also calls Fan::tachChanged().
260 *
261 * @param[in] msg - the dbus message
262 */
263 void handleTargetChange(sdbusplus::message::message& msg);
Matt Spinlerabf8da32017-04-27 14:08:45 -0500264
Matthew Barth177fe982020-05-26 11:05:19 -0500265 /**
266 * @brief Reads the Value property and stores in _tachInput.
267 * Also calls Fan::tachChanged().
268 *
269 * @param[in] msg - the dbus message
270 */
271 void handleTachChange(sdbusplus::message::message& msg);
Matt Spinlerebaae612017-04-27 14:21:48 -0500272
Matthew Barth177fe982020-05-26 11:05:19 -0500273 /**
274 * @brief Updates the Functional property in the inventory
275 * for this tach sensor based on the value passed in.
276 *
277 * @param[in] functional - If the Functional property should
278 * be set to true or false.
279 */
280 void updateInventory(bool functional);
Matt Spinlerebaae612017-04-27 14:21:48 -0500281
Matthew Barth177fe982020-05-26 11:05:19 -0500282 /**
283 * @brief the dbus object
284 */
285 sdbusplus::bus::bus& _bus;
Matt Spinlerebaae612017-04-27 14:21:48 -0500286
Matthew Barth177fe982020-05-26 11:05:19 -0500287 /**
288 * @brief Reference to the parent Fan object
289 */
290 Fan& _fan;
Matt Spinlerebaae612017-04-27 14:21:48 -0500291
Matthew Barth177fe982020-05-26 11:05:19 -0500292 /**
293 * @brief The name of the sensor, including the full path
294 *
295 * For example /xyz/openbmc_project/sensors/fan_tach/fan0
296 */
297 const std::string _name;
Matt Spinlerabf8da32017-04-27 14:08:45 -0500298
Matthew Barth177fe982020-05-26 11:05:19 -0500299 /**
300 * @brief The inventory name of the sensor, including the full path
301 */
302 const std::string _invName;
Matt Spinlerabf8da32017-04-27 14:08:45 -0500303
Matthew Barth177fe982020-05-26 11:05:19 -0500304 /**
305 * @brief If functional (not too slow). The parent
306 * fan object sets this.
307 */
308 bool _functional;
Matt Spinlerabf8da32017-04-27 14:08:45 -0500309
Matthew Barth177fe982020-05-26 11:05:19 -0500310 /**
311 * @brief If the sensor has a Target property (can set speed)
312 */
313 const bool _hasTarget;
Matthew Barth4d982852017-11-17 09:37:13 -0600314
Matthew Barth177fe982020-05-26 11:05:19 -0500315 /**
316 * @brief Amount of time to delay updating to functional
317 */
318 const size_t _funcDelay;
Matt Spinlerabf8da32017-04-27 14:08:45 -0500319
Matthew Barth177fe982020-05-26 11:05:19 -0500320 /**
321 * @brief The interface that the target implements
322 */
323 const std::string _interface;
Matt Spinlerabf8da32017-04-27 14:08:45 -0500324
Matthew Barth177fe982020-05-26 11:05:19 -0500325 /**
326 * @brief The factor of target to get fan rpm
327 */
328 const double _factor;
Matthew Barth9396bcc2018-02-19 14:13:20 -0600329
Matthew Barth177fe982020-05-26 11:05:19 -0500330 /**
331 * @brief The offset of target to get fan rpm
332 */
333 const int64_t _offset;
Lei YU80f271b2018-01-31 15:24:46 +0800334
Matthew Barth177fe982020-05-26 11:05:19 -0500335 /**
Jolie Ku69f2f482020-10-21 09:59:43 +0800336 * @brief The method of out of range
337 */
338 const size_t _method;
339
340 /**
341 * @brief The threshold for count method
342 */
343 const size_t _threshold;
344
345 /**
346 * @brief The counter for count method
347 */
348 size_t _counter = 0;
349
350 /**
Matthew Barth177fe982020-05-26 11:05:19 -0500351 * @brief The input speed, from the Value dbus property
352 */
Matthew Barth0891e3b2020-08-13 12:00:23 -0500353 double _tachInput = 0;
Lei YU8e5d1972018-01-26 17:14:00 +0800354
Matthew Barth177fe982020-05-26 11:05:19 -0500355 /**
356 * @brief The current target speed, from the Target dbus property
357 * (if applicable)
358 */
359 uint64_t _tachTarget = 0;
Lei YU8e5d1972018-01-26 17:14:00 +0800360
Matthew Barth177fe982020-05-26 11:05:19 -0500361 /**
362 * @brief The timeout value to use
363 */
364 const size_t _timeout;
Matt Spinlerabf8da32017-04-27 14:08:45 -0500365
Matthew Barth177fe982020-05-26 11:05:19 -0500366 /**
367 * @brief Mode that current timer is in
368 */
369 TimerMode _timerMode;
Matt Spinlerabf8da32017-04-27 14:08:45 -0500370
Matthew Barth177fe982020-05-26 11:05:19 -0500371 /**
372 * The timer object
373 */
374 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> _timer;
Matt Spinlerebaae612017-04-27 14:21:48 -0500375
Matthew Barth177fe982020-05-26 11:05:19 -0500376 /**
377 * @brief The match object for the Value properties changed signal
378 */
379 std::unique_ptr<sdbusplus::server::match::match> tachSignal;
Matthew Barth3800ae72018-02-19 16:08:04 -0600380
Matthew Barth177fe982020-05-26 11:05:19 -0500381 /**
382 * @brief The match object for the Target properties changed signal
383 */
384 std::unique_ptr<sdbusplus::server::match::match> targetSignal;
Matt Spinlerf13b42e2020-10-26 15:29:49 -0500385
386 /**
387 * @brief The number of seconds to wait between a sensor being set
388 * to nonfunctional and creating an error for it.
389 *
390 * If std::nullopt, no errors will be created.
391 */
392 const std::optional<size_t> _errorDelay;
393
394 /**
395 * @brief The timer that uses _errorDelay. When it expires an error
396 * will be created for a faulted fan sensor (rotor).
397 *
398 * If _errorDelay is std::nullopt, then this won't be created.
399 */
400 std::unique_ptr<
401 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>
402 _errorTimer;
Matt Spinlerabf8da32017-04-27 14:08:45 -0500403};
404
Matthew Barth177fe982020-05-26 11:05:19 -0500405} // namespace monitor
406} // namespace fan
407} // namespace phosphor