blob: 814df6934492a73922fd864a5c7f977791b09fd1 [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/**
Matt Spinlerabf8da32017-04-27 14:08:45 -050045 * @class TachSensor
46 *
47 * This class represents the sensor that reads a tach value.
48 * It may also support a Target, which is the property used to
49 * set a speed. Since it doesn't necessarily have a Target, it
50 * won't for sure know if it is running too slow, so it leaves
51 * that determination to other code.
52 *
53 * This class has a parent Fan object that knows about all
54 * sensors for that fan.
55 */
56class TachSensor
57{
Matthew Barth177fe982020-05-26 11:05:19 -050058 public:
59 TachSensor() = delete;
60 TachSensor(const TachSensor&) = delete;
61 // TachSensor is not moveable since the this pointer is used as systemd
62 // callback context.
63 TachSensor(TachSensor&&) = delete;
64 TachSensor& operator=(const TachSensor&) = delete;
65 TachSensor& operator=(TachSensor&&) = delete;
66 ~TachSensor() = default;
Matt Spinlerabf8da32017-04-27 14:08:45 -050067
Matthew Barth177fe982020-05-26 11:05:19 -050068 /**
69 * @brief Constructor
70 *
71 * @param[in] mode - mode of fan monitor
72 * @param[in] bus - the dbus object
73 * @param[in] fan - the parent fan object
74 * @param[in] id - the id of the sensor
75 * @param[in] hasTarget - if the sensor supports
76 * setting the speed
77 * @param[in] funcDelay - Delay to mark functional
78 * @param[in] interface - the interface of the target
79 * @param[in] factor - the factor of the sensor target
80 * @param[in] offset - the offset of the sensor target
81 * @param[in] timeout - Normal timeout value to use
Matt Spinlerf13b42e2020-10-26 15:29:49 -050082 * @param[in] errorDelay - Delay in seconds before creating an error
83 * or std::nullopt if no errors.
84 *
Matthew Barth177fe982020-05-26 11:05:19 -050085 * @param[in] event - Event loop reference
86 */
87 TachSensor(Mode mode, sdbusplus::bus::bus& bus, Fan& fan,
88 const std::string& id, bool hasTarget, size_t funcDelay,
89 const std::string& interface, double factor, int64_t offset,
Matt Spinlerf13b42e2020-10-26 15:29:49 -050090 size_t timeout, const std::optional<size_t>& errorDelay,
91 const sdeventplus::Event& event);
Matt Spinlerabf8da32017-04-27 14:08:45 -050092
Matthew Barth177fe982020-05-26 11:05:19 -050093 /**
94 * @brief Returns the target speed value
95 */
96 uint64_t getTarget() const;
Matt Spinlerabf8da32017-04-27 14:08:45 -050097
Matthew Barth177fe982020-05-26 11:05:19 -050098 /**
99 * @brief Returns the input speed value
100 */
Matthew Barth0891e3b2020-08-13 12:00:23 -0500101 inline double getInput() const
Matthew Barth177fe982020-05-26 11:05:19 -0500102 {
103 return _tachInput;
104 }
Matt Spinlerabf8da32017-04-27 14:08:45 -0500105
Matthew Barth177fe982020-05-26 11:05:19 -0500106 /**
107 * @brief Returns true if sensor has a target
108 */
109 inline bool hasTarget() const
110 {
111 return _hasTarget;
112 }
Matt Spinlerabf8da32017-04-27 14:08:45 -0500113
Matthew Barth177fe982020-05-26 11:05:19 -0500114 /**
115 * @brief Returns the interface of the sensor target
116 */
117 inline std::string getInterface() const
118 {
119 return _interface;
120 }
Matt Spinlerabf8da32017-04-27 14:08:45 -0500121
Matthew Barth177fe982020-05-26 11:05:19 -0500122 /**
123 * @brief Returns the factor of the sensor target
124 */
125 inline double getFactor() const
126 {
127 return _factor;
128 }
Lei YU80f271b2018-01-31 15:24:46 +0800129
Matthew Barth177fe982020-05-26 11:05:19 -0500130 /**
131 * @brief Returns the offset of the sensor target
132 */
133 inline int64_t getOffset() const
134 {
135 return _offset;
136 }
Lei YU8e5d1972018-01-26 17:14:00 +0800137
Matthew Barth177fe982020-05-26 11:05:19 -0500138 /**
139 * Returns true if the hardware behind this
140 * sensor is considered working OK/functional.
141 */
142 inline bool functional() const
143 {
144 return _functional;
145 }
Lei YU8e5d1972018-01-26 17:14:00 +0800146
Matthew Barth177fe982020-05-26 11:05:19 -0500147 /**
148 * Set the functional status and update inventory to match
149 */
150 void setFunctional(bool functional);
Matt Spinlerabf8da32017-04-27 14:08:45 -0500151
Matthew Barth177fe982020-05-26 11:05:19 -0500152 /**
153 * @brief Says if the timer is running or not
154 *
155 * @return bool - if timer is currently running
156 */
157 inline bool timerRunning()
158 {
159 return _timer.isEnabled();
160 }
Matt Spinlerabf8da32017-04-27 14:08:45 -0500161
Matthew Barth177fe982020-05-26 11:05:19 -0500162 /**
163 * @brief Stops the timer when the given mode differs and starts
164 * the associated timer for the mode given if not already running
165 *
166 * @param[in] mode - mode of timer to start
167 */
168 void startTimer(TimerMode mode);
Matt Spinler6fa181c2017-09-27 16:24:45 -0500169
Matthew Barth177fe982020-05-26 11:05:19 -0500170 /**
171 * @brief Stops the timer
172 */
173 inline void stopTimer()
174 {
175 _timer.setEnabled(false);
176 }
Matt Spinler6fa181c2017-09-27 16:24:45 -0500177
Matthew Barth177fe982020-05-26 11:05:19 -0500178 /**
179 * @brief Return the given timer mode's delay time
180 *
181 * @param[in] mode - mode of timer to get delay time for
182 */
183 std::chrono::microseconds getDelay(TimerMode mode);
Matt Spinlera9406a72017-04-27 14:29:24 -0500184
Matthew Barth177fe982020-05-26 11:05:19 -0500185 /**
186 * Returns the sensor name
187 */
188 inline const std::string& name() const
189 {
190 return _name;
191 };
Matt Spinlera9406a72017-04-27 14:29:24 -0500192
Matt Spinlerf13b42e2020-10-26 15:29:49 -0500193 /**
194 * @brief Says if the error timer is running
195 *
196 * @return bool - If the timer is running
197 */
198 bool errorTimerRunning() const
199 {
200 if (_errorTimer && _errorTimer->isEnabled())
201 {
202 return true;
203 }
204 return false;
205 }
206
Matthew Barth177fe982020-05-26 11:05:19 -0500207 private:
208 /**
209 * @brief Returns the match string to use for matching
210 * on a properties changed signal.
211 */
212 std::string getMatchString(const std::string& interface);
Matt Spinlerce75b512017-07-26 15:10:48 -0500213
Matthew Barth177fe982020-05-26 11:05:19 -0500214 /**
215 * @brief Reads the Target property and stores in _tachTarget.
216 * Also calls Fan::tachChanged().
217 *
218 * @param[in] msg - the dbus message
219 */
220 void handleTargetChange(sdbusplus::message::message& msg);
Matt Spinlerabf8da32017-04-27 14:08:45 -0500221
Matthew Barth177fe982020-05-26 11:05:19 -0500222 /**
223 * @brief Reads the Value property and stores in _tachInput.
224 * Also calls Fan::tachChanged().
225 *
226 * @param[in] msg - the dbus message
227 */
228 void handleTachChange(sdbusplus::message::message& msg);
Matt Spinlerebaae612017-04-27 14:21:48 -0500229
Matthew Barth177fe982020-05-26 11:05:19 -0500230 /**
231 * @brief Updates the Functional property in the inventory
232 * for this tach sensor based on the value passed in.
233 *
234 * @param[in] functional - If the Functional property should
235 * be set to true or false.
236 */
237 void updateInventory(bool functional);
Matt Spinlerebaae612017-04-27 14:21:48 -0500238
Matthew Barth177fe982020-05-26 11:05:19 -0500239 /**
240 * @brief the dbus object
241 */
242 sdbusplus::bus::bus& _bus;
Matt Spinlerebaae612017-04-27 14:21:48 -0500243
Matthew Barth177fe982020-05-26 11:05:19 -0500244 /**
245 * @brief Reference to the parent Fan object
246 */
247 Fan& _fan;
Matt Spinlerebaae612017-04-27 14:21:48 -0500248
Matthew Barth177fe982020-05-26 11:05:19 -0500249 /**
250 * @brief The name of the sensor, including the full path
251 *
252 * For example /xyz/openbmc_project/sensors/fan_tach/fan0
253 */
254 const std::string _name;
Matt Spinlerabf8da32017-04-27 14:08:45 -0500255
Matthew Barth177fe982020-05-26 11:05:19 -0500256 /**
257 * @brief The inventory name of the sensor, including the full path
258 */
259 const std::string _invName;
Matt Spinlerabf8da32017-04-27 14:08:45 -0500260
Matthew Barth177fe982020-05-26 11:05:19 -0500261 /**
262 * @brief If functional (not too slow). The parent
263 * fan object sets this.
264 */
265 bool _functional;
Matt Spinlerabf8da32017-04-27 14:08:45 -0500266
Matthew Barth177fe982020-05-26 11:05:19 -0500267 /**
268 * @brief If the sensor has a Target property (can set speed)
269 */
270 const bool _hasTarget;
Matthew Barth4d982852017-11-17 09:37:13 -0600271
Matthew Barth177fe982020-05-26 11:05:19 -0500272 /**
273 * @brief Amount of time to delay updating to functional
274 */
275 const size_t _funcDelay;
Matt Spinlerabf8da32017-04-27 14:08:45 -0500276
Matthew Barth177fe982020-05-26 11:05:19 -0500277 /**
278 * @brief The interface that the target implements
279 */
280 const std::string _interface;
Matt Spinlerabf8da32017-04-27 14:08:45 -0500281
Matthew Barth177fe982020-05-26 11:05:19 -0500282 /**
283 * @brief The factor of target to get fan rpm
284 */
285 const double _factor;
Matthew Barth9396bcc2018-02-19 14:13:20 -0600286
Matthew Barth177fe982020-05-26 11:05:19 -0500287 /**
288 * @brief The offset of target to get fan rpm
289 */
290 const int64_t _offset;
Lei YU80f271b2018-01-31 15:24:46 +0800291
Matthew Barth177fe982020-05-26 11:05:19 -0500292 /**
293 * @brief The input speed, from the Value dbus property
294 */
Matthew Barth0891e3b2020-08-13 12:00:23 -0500295 double _tachInput = 0;
Lei YU8e5d1972018-01-26 17:14:00 +0800296
Matthew Barth177fe982020-05-26 11:05:19 -0500297 /**
298 * @brief The current target speed, from the Target dbus property
299 * (if applicable)
300 */
301 uint64_t _tachTarget = 0;
Lei YU8e5d1972018-01-26 17:14:00 +0800302
Matthew Barth177fe982020-05-26 11:05:19 -0500303 /**
304 * @brief The timeout value to use
305 */
306 const size_t _timeout;
Matt Spinlerabf8da32017-04-27 14:08:45 -0500307
Matthew Barth177fe982020-05-26 11:05:19 -0500308 /**
309 * @brief Mode that current timer is in
310 */
311 TimerMode _timerMode;
Matt Spinlerabf8da32017-04-27 14:08:45 -0500312
Matthew Barth177fe982020-05-26 11:05:19 -0500313 /**
314 * The timer object
315 */
316 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> _timer;
Matt Spinlerebaae612017-04-27 14:21:48 -0500317
Matthew Barth177fe982020-05-26 11:05:19 -0500318 /**
319 * @brief The match object for the Value properties changed signal
320 */
321 std::unique_ptr<sdbusplus::server::match::match> tachSignal;
Matthew Barth3800ae72018-02-19 16:08:04 -0600322
Matthew Barth177fe982020-05-26 11:05:19 -0500323 /**
324 * @brief The match object for the Target properties changed signal
325 */
326 std::unique_ptr<sdbusplus::server::match::match> targetSignal;
Matt Spinlerf13b42e2020-10-26 15:29:49 -0500327
328 /**
329 * @brief The number of seconds to wait between a sensor being set
330 * to nonfunctional and creating an error for it.
331 *
332 * If std::nullopt, no errors will be created.
333 */
334 const std::optional<size_t> _errorDelay;
335
336 /**
337 * @brief The timer that uses _errorDelay. When it expires an error
338 * will be created for a faulted fan sensor (rotor).
339 *
340 * If _errorDelay is std::nullopt, then this won't be created.
341 */
342 std::unique_ptr<
343 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>
344 _errorTimer;
Matt Spinlerabf8da32017-04-27 14:08:45 -0500345};
346
Matthew Barth177fe982020-05-26 11:05:19 -0500347} // namespace monitor
348} // namespace fan
349} // namespace phosphor