xref: /openbmc/phosphor-fan-presence/monitor/fan.hpp (revision fcb0dbcb144020606780da9dd2e2be517ef7cf6d)
1abf8da36SMatt Spinler #pragma once
2abf8da36SMatt Spinler 
3b0412d07SMatt Spinler #include "config.h"
4b0412d07SMatt Spinler 
5abf8da36SMatt Spinler #include "tach_sensor.hpp"
6c39e859bSMatt Spinler #include "trust_manager.hpp"
7abf8da36SMatt Spinler #include "types.hpp"
8abf8da36SMatt Spinler 
9177fe986SMatthew Barth #include <sdbusplus/bus.hpp>
10177fe986SMatthew Barth #include <sdeventplus/event.hpp>
11177fe986SMatthew Barth 
12177fe986SMatthew Barth #include <tuple>
13177fe986SMatthew Barth #include <vector>
14177fe986SMatthew Barth 
15abf8da36SMatt Spinler namespace phosphor
16abf8da36SMatt Spinler {
17abf8da36SMatt Spinler namespace fan
18abf8da36SMatt Spinler {
19abf8da36SMatt Spinler namespace monitor
20abf8da36SMatt Spinler {
21abf8da36SMatt Spinler 
22b0412d07SMatt Spinler class System;
23b0412d07SMatt Spinler 
24edaeb31cSBrad Bishop /**
25edaeb31cSBrad Bishop  * @class InvalidSensorError
26edaeb31cSBrad Bishop  *
27edaeb31cSBrad Bishop  * An exception type for sensors that don't exist or
28edaeb31cSBrad Bishop  * are otherwise inaccessible.
29edaeb31cSBrad Bishop  */
30177fe986SMatthew Barth class InvalidSensorError : public std::exception
31177fe986SMatthew Barth {};
32abf8da36SMatt Spinler 
33abf8da36SMatt Spinler /**
34abf8da36SMatt Spinler  * @class Fan
35abf8da36SMatt Spinler  *
36abf8da36SMatt Spinler  * Represents a fan, which can contain 1 or more sensors which
37abf8da36SMatt Spinler  * loosely correspond to rotors.  See below.
38abf8da36SMatt Spinler  *
39abf8da36SMatt Spinler  * There is a sensor when hwmon exposes one, which means there is a
40abf8da36SMatt Spinler  * speed value to be read.  Sometimes there is a sensor per rotor,
41abf8da36SMatt Spinler  * and other times multiple rotors just use 1 sensor total where
42abf8da36SMatt Spinler  * the sensor reports the slowest speed of all of the rotors.
43abf8da36SMatt Spinler  *
44abf8da36SMatt Spinler  * A rotor's speed is set by writing the Target value of a sensor.
45abf8da36SMatt Spinler  * Sometimes each sensor in a fan supports having a Target, and other
46abf8da36SMatt Spinler  * times not all of them do.  A TachSensor object knows if it supports
47abf8da36SMatt Spinler  * the Target property.
48abf8da36SMatt Spinler  *
49abf8da36SMatt Spinler  * The strategy for monitoring fan speeds is as follows:
50abf8da36SMatt Spinler  *
51abf8da36SMatt Spinler  * Every time a Target (new speed written) or Input (actual speed read)
52abf8da36SMatt Spinler  * sensor changes, check if the input value is within some range of the target
53abf8da36SMatt Spinler  * value.  If it isn't, start a timer at the end of which the sensor will be
54abf8da36SMatt Spinler  * set to not functional.  If enough sensors in the fan are now nonfunctional,
55abf8da36SMatt Spinler  * set the whole fan to nonfunctional in the inventory.
56abf8da36SMatt Spinler  *
57abf8da36SMatt Spinler  * When sensor inputs come back within a specified range of the target,
58abf8da36SMatt Spinler  * stop its timer if running, make the sensor functional again if it wasn't,
59abf8da36SMatt Spinler  * and if enough sensors in the fan are now functional set the whole fan
60abf8da36SMatt Spinler  * back to functional in the inventory.
61abf8da36SMatt Spinler  */
62abf8da36SMatt Spinler class Fan
63abf8da36SMatt Spinler {
64b1e18514SMatt Spinler     using Property = std::string;
65c21d0b36SPatrick Williams     using Value = std::variant<bool>;
66b1e18514SMatt Spinler     using PropertyMap = std::map<Property, Value>;
67b1e18514SMatt Spinler 
68b1e18514SMatt Spinler     using Interface = std::string;
69b1e18514SMatt Spinler     using InterfaceMap = std::map<Interface, PropertyMap>;
70b1e18514SMatt Spinler 
71b1e18514SMatt Spinler     using Object = sdbusplus::message::object_path;
72b1e18514SMatt Spinler     using ObjectMap = std::map<Object, InterfaceMap>;
73abf8da36SMatt Spinler 
74abf8da36SMatt Spinler   public:
75abf8da36SMatt Spinler     Fan() = delete;
76abf8da36SMatt Spinler     Fan(const Fan&) = delete;
77abf8da36SMatt Spinler     Fan(Fan&&) = default;
78abf8da36SMatt Spinler     Fan& operator=(const Fan&) = delete;
79abf8da36SMatt Spinler     Fan& operator=(Fan&&) = default;
80abf8da36SMatt Spinler     ~Fan() = default;
81abf8da36SMatt Spinler 
82abf8da36SMatt Spinler     /**
83abf8da36SMatt Spinler      * @brief Constructor
84abf8da36SMatt Spinler      *
856ad28430SMatthew Barth      * @param mode - mode of fan monitor
86abf8da36SMatt Spinler      * @param bus - the dbus object
871cfc2f11SWilliam A. Kennington III      * @param event - event loop reference
88c39e859bSMatt Spinler      * @param trust - the tach trust manager
89abf8da36SMatt Spinler      * @param def - the fan definition structure
90b0412d07SMatt Spinler      * @param system - Reference to the system object
91abf8da36SMatt Spinler      */
92177fe986SMatthew Barth     Fan(Mode mode, sdbusplus::bus::bus& bus, const sdeventplus::Event& event,
93b0412d07SMatt Spinler         std::unique_ptr<trust::Manager>& trust, const FanDefinition& def,
94b0412d07SMatt Spinler         System& system);
95abf8da36SMatt Spinler 
96ebaae611SMatt Spinler     /**
97ebaae611SMatt Spinler      * @brief Callback function for when an input sensor changes
98ebaae611SMatt Spinler      *
99ebaae611SMatt Spinler      * Starts a timer, where if it expires then the sensor
100a9406a77SMatt Spinler      * was out of range for too long and can be considered not functional.
101ebaae611SMatt Spinler      */
102ebaae611SMatt Spinler     void tachChanged(TachSensor& sensor);
103ebaae611SMatt Spinler 
104ebaae611SMatt Spinler     /**
105ebaae611SMatt Spinler      * @brief Calls tachChanged(sensor) on each sensor
106ebaae611SMatt Spinler      */
107ebaae611SMatt Spinler     void tachChanged();
108abf8da36SMatt Spinler 
109a9406a77SMatt Spinler     /**
11069f2f48eSJolie Ku      * @brief The callback function for the method
111a9406a77SMatt Spinler      *
112a9406a77SMatt Spinler      * Sets the sensor to not functional.
113a9406a77SMatt Spinler      * If enough sensors are now not functional,
114a9406a77SMatt Spinler      * updates the functional status of the whole
115a9406a77SMatt Spinler      * fan in the inventory.
116a9406a77SMatt Spinler      *
11769f2f48eSJolie Ku      * @param[in] sensor - the sensor for state update
118a9406a77SMatt Spinler      */
11969f2f48eSJolie Ku     void updateState(TachSensor& sensor);
120a9406a77SMatt Spinler 
1214d982856SMatthew Barth     /**
1224d982856SMatthew Barth      * @brief Get the name of the fan
1234d982856SMatthew Barth      *
1244d982856SMatthew Barth      * @return - The fan name
1254d982856SMatthew Barth      */
1264d982856SMatthew Barth     inline const std::string& getName() const
1274d982856SMatthew Barth     {
1284d982856SMatthew Barth         return _name;
1294d982856SMatthew Barth     }
1304d982856SMatthew Barth 
131f552ea5cSMatthew Barth     /**
132f552ea5cSMatthew Barth      * @brief Finds the target speed of this fan
133f552ea5cSMatthew Barth      *
134f552ea5cSMatthew Barth      * Finds the target speed from the list of sensors that make up this
135f552ea5cSMatthew Barth      * fan. At least one sensor should contain a target speed value.
136f552ea5cSMatthew Barth      *
137f552ea5cSMatthew Barth      * @return - The target speed found from the list of sensors on the fan
138f552ea5cSMatthew Barth      */
139f552ea5cSMatthew Barth     uint64_t findTargetSpeed();
140f552ea5cSMatthew Barth 
141b63aa09eSMatt Spinler     /**
142b63aa09eSMatt Spinler      * @brief Returns the contained TachSensor objects
143b63aa09eSMatt Spinler      *
144b63aa09eSMatt Spinler      * @return std::vector<std::shared_ptr<TachSensor>> - The sensors
145b63aa09eSMatt Spinler      */
146b63aa09eSMatt Spinler     const std::vector<std::shared_ptr<TachSensor>>& sensors() const
147b63aa09eSMatt Spinler     {
148b63aa09eSMatt Spinler         return _sensors;
149b63aa09eSMatt Spinler     }
150b63aa09eSMatt Spinler 
151b63aa09eSMatt Spinler     /**
152b63aa09eSMatt Spinler      * @brief Returns the presence status of the fan
153b63aa09eSMatt Spinler      *
154b63aa09eSMatt Spinler      * @return bool - If the fan is present or not
155b63aa09eSMatt Spinler      */
156b63aa09eSMatt Spinler     bool present() const
157b63aa09eSMatt Spinler     {
158b63aa09eSMatt Spinler         return _present;
159b63aa09eSMatt Spinler     }
160b63aa09eSMatt Spinler 
161f13b42e2SMatt Spinler     /**
162f13b42e2SMatt Spinler      * @brief Called from TachSensor when its error timer expires
163f13b42e2SMatt Spinler      *        so an event log calling out the fan can be created.
164f13b42e2SMatt Spinler      *
165f13b42e2SMatt Spinler      * @param[in] sensor - The nonfunctional sensor
166f13b42e2SMatt Spinler      */
167f13b42e2SMatt Spinler     void sensorErrorTimerExpired(const TachSensor& sensor);
168f13b42e2SMatt Spinler 
169*fcb0dbcbSMatthew Barth     /**
170*fcb0dbcbSMatthew Barth      * @brief Process the state of the given tach sensor without checking
171*fcb0dbcbSMatthew Barth      * any trust groups the sensor may be included in
172*fcb0dbcbSMatthew Barth      *
173*fcb0dbcbSMatthew Barth      * @param[in] sensor - Tach sensor to process
174*fcb0dbcbSMatthew Barth      *
175*fcb0dbcbSMatthew Barth      * This function is intended to check the current state of a tach sensor
176*fcb0dbcbSMatthew Barth      * regardless of whether or not the tach sensor is configured to be in any
177*fcb0dbcbSMatthew Barth      * trust groups.
178*fcb0dbcbSMatthew Barth      */
179*fcb0dbcbSMatthew Barth     void process(TachSensor& sensor);
180*fcb0dbcbSMatthew Barth 
181abf8da36SMatt Spinler   private:
182abf8da36SMatt Spinler     /**
183abf8da36SMatt Spinler      * @brief Returns true if the sensor input is not within
184abf8da36SMatt Spinler      * some deviation of the target.
185abf8da36SMatt Spinler      *
186abf8da36SMatt Spinler      * @param[in] sensor - the sensor to check
187abf8da36SMatt Spinler      */
188abf8da36SMatt Spinler     bool outOfRange(const TachSensor& sensor);
189abf8da36SMatt Spinler 
190abf8da36SMatt Spinler     /**
1917c23a049SMatthew Barth      * @brief Returns the number sensors that are nonfunctional
192abf8da36SMatt Spinler      */
1937c23a049SMatthew Barth     size_t countNonFunctionalSensors();
194abf8da36SMatt Spinler 
195b1e18514SMatt Spinler     /**
196b1e18514SMatt Spinler      * @brief Updates the Functional property in the inventory
197b1e18514SMatt Spinler      *        for the fan based on the value passed in.
198b1e18514SMatt Spinler      *
199b1e18514SMatt Spinler      * @param[in] functional - If the Functional property should
200b1e18514SMatt Spinler      *                         be set to true or false.
201b1e18514SMatt Spinler      */
202b1e18514SMatt Spinler     void updateInventory(bool functional);
203b1e18514SMatt Spinler 
204b1e18514SMatt Spinler     /**
205b0412d07SMatt Spinler      * @brief Called by _monitorTimer to start fan monitoring some
206b0412d07SMatt Spinler      *        amount of time after startup.
207b0412d07SMatt Spinler      */
208b0412d07SMatt Spinler     void startMonitor();
209b0412d07SMatt Spinler 
210b0412d07SMatt Spinler     /**
211b63aa09eSMatt Spinler      * @brief Called when the fan presence property changes on D-Bus
212b63aa09eSMatt Spinler      *
213b63aa09eSMatt Spinler      * @param[in] msg - The message from the propertiesChanged signal
214b63aa09eSMatt Spinler      */
215b63aa09eSMatt Spinler     void presenceChanged(sdbusplus::message::message& msg);
216b63aa09eSMatt Spinler 
217b63aa09eSMatt Spinler     /**
218abf8da36SMatt Spinler      * @brief the dbus object
219abf8da36SMatt Spinler      */
220abf8da36SMatt Spinler     sdbusplus::bus::bus& _bus;
221abf8da36SMatt Spinler 
222abf8da36SMatt Spinler     /**
223abf8da36SMatt Spinler      * @brief The inventory name of the fan
224abf8da36SMatt Spinler      */
225abf8da36SMatt Spinler     const std::string _name;
226abf8da36SMatt Spinler 
227abf8da36SMatt Spinler     /**
228abf8da36SMatt Spinler      * @brief The percentage that the input speed must be below
229abf8da36SMatt Spinler      *        the target speed to be considered an error.
230abf8da36SMatt Spinler      *        Between 0 and 100.
231abf8da36SMatt Spinler      */
232abf8da36SMatt Spinler     const size_t _deviation;
233abf8da36SMatt Spinler 
234abf8da36SMatt Spinler     /**
235abf8da36SMatt Spinler      * The number of sensors that must be nonfunctional at the
236abf8da36SMatt Spinler      * same time in order for the fan to be set to nonfunctional
237abf8da36SMatt Spinler      * in the inventory.
238abf8da36SMatt Spinler      */
239abf8da36SMatt Spinler     const size_t _numSensorFailsForNonFunc;
240abf8da36SMatt Spinler 
241abf8da36SMatt Spinler     /**
2425d564a9fSJolie Ku      * The number of failed sensors
2435d564a9fSJolie Ku      */
2445d564a9fSJolie Ku     size_t _numFailedSensor = 0;
2455d564a9fSJolie Ku 
2465d564a9fSJolie Ku     /**
247abf8da36SMatt Spinler      * @brief The current functional state of the fan
248abf8da36SMatt Spinler      */
249abf8da36SMatt Spinler     bool _functional = true;
250abf8da36SMatt Spinler 
251abf8da36SMatt Spinler     /**
252abf8da36SMatt Spinler      * The sensor objects for the fan
253abf8da36SMatt Spinler      */
25432affb98SMatthew Barth     std::vector<std::shared_ptr<TachSensor>> _sensors;
255c39e859bSMatt Spinler 
256c39e859bSMatt Spinler     /**
257c39e859bSMatt Spinler      * The tach trust manager object
258c39e859bSMatt Spinler      */
259c39e859bSMatt Spinler     std::unique_ptr<trust::Manager>& _trustManager;
260b0412d07SMatt Spinler 
261b0412d07SMatt Spinler #ifdef MONITOR_USE_JSON
262b0412d07SMatt Spinler     /**
263b0412d07SMatt Spinler      * @brief The number of seconds to wait after startup until
264b0412d07SMatt Spinler      *        fan sensors should checked against their targets.
265b0412d07SMatt Spinler      */
266b0412d07SMatt Spinler     size_t _monitorDelay;
267b0412d07SMatt Spinler 
268b0412d07SMatt Spinler     /**
269b0412d07SMatt Spinler      * @brief Expires after _monitorDelay to start fan monitoring.
270b0412d07SMatt Spinler      */
271b0412d07SMatt Spinler     sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> _monitorTimer;
272b0412d07SMatt Spinler #endif
273b0412d07SMatt Spinler 
274b0412d07SMatt Spinler     /**
275b0412d07SMatt Spinler      * @brief Set to true when monitoring can start.
276b0412d07SMatt Spinler      */
277b0412d07SMatt Spinler     bool _monitorReady = false;
278b0412d07SMatt Spinler 
279b0412d07SMatt Spinler     /**
280b0412d07SMatt Spinler      * @brief Reference to the System object
281b0412d07SMatt Spinler      */
282b0412d07SMatt Spinler     System& _system;
283b63aa09eSMatt Spinler 
284b63aa09eSMatt Spinler     /**
285b63aa09eSMatt Spinler      * @brief The match object for propertiesChanged signals
286b63aa09eSMatt Spinler      *        for the inventory item interface to track the
287b63aa09eSMatt Spinler      *        Present property.
288b63aa09eSMatt Spinler      */
289b63aa09eSMatt Spinler     sdbusplus::bus::match::match _presenceMatch;
290b63aa09eSMatt Spinler 
291b63aa09eSMatt Spinler     /**
292b63aa09eSMatt Spinler      * @brief The current presence state
293b63aa09eSMatt Spinler      */
294b63aa09eSMatt Spinler     bool _present = false;
29527f6b686SMatt Spinler 
29627f6b686SMatt Spinler     /**
29727f6b686SMatt Spinler      * @brief The number of seconds to wait after a fan is removed before
29827f6b686SMatt Spinler      *        creating an event log for it.  If std::nullopt, then no
29927f6b686SMatt Spinler      *        event log will be created.
30027f6b686SMatt Spinler      */
30127f6b686SMatt Spinler     const std::optional<size_t> _fanMissingErrorDelay;
30227f6b686SMatt Spinler 
30327f6b686SMatt Spinler     /**
30427f6b686SMatt Spinler      * @brief The timer that uses the _fanMissingErrorDelay timeout,
30527f6b686SMatt Spinler      *        at the end of which an event log will be created.
30627f6b686SMatt Spinler      */
30727f6b686SMatt Spinler     std::unique_ptr<
30827f6b686SMatt Spinler         sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>
30927f6b686SMatt Spinler         _fanMissingErrorTimer;
310abf8da36SMatt Spinler };
311abf8da36SMatt Spinler 
312177fe986SMatthew Barth } // namespace monitor
313177fe986SMatthew Barth } // namespace fan
314177fe986SMatthew Barth } // namespace phosphor
315