1 #pragma once
2 
3 #include "config.h"
4 
5 #include "tach_sensor.hpp"
6 #include "trust_manager.hpp"
7 #include "types.hpp"
8 
9 #include <sdbusplus/bus.hpp>
10 #include <sdeventplus/event.hpp>
11 
12 #include <tuple>
13 #include <vector>
14 
15 namespace phosphor
16 {
17 namespace fan
18 {
19 namespace monitor
20 {
21 
22 class System;
23 
24 /**
25  * @class Fan
26  *
27  * Represents a fan, which can contain 1 or more sensors which
28  * loosely correspond to rotors.  See below.
29  *
30  * There is a sensor when hwmon exposes one, which means there is a
31  * speed value to be read.  Sometimes there is a sensor per rotor,
32  * and other times multiple rotors just use 1 sensor total where
33  * the sensor reports the slowest speed of all of the rotors.
34  *
35  * A rotor's speed is set by writing the Target value of a sensor.
36  * Sometimes each sensor in a fan supports having a Target, and other
37  * times not all of them do.  A TachSensor object knows if it supports
38  * the Target property.
39  *
40  * The strategy for monitoring fan speeds is as follows:
41  *
42  * Every time a Target (new speed written) or Input (actual speed read)
43  * sensor changes, check if the input value is within some range of the target
44  * value.  If it isn't, start a timer at the end of which the sensor will be
45  * set to not functional.  If enough sensors in the fan are now nonfunctional,
46  * set the whole fan to nonfunctional in the inventory.
47  *
48  * When sensor inputs come back within a specified range of the target,
49  * stop its timer if running, make the sensor functional again if it wasn't,
50  * and if enough sensors in the fan are now functional set the whole fan
51  * back to functional in the inventory.
52  */
53 class Fan
54 {
55     using Property = std::string;
56     using Value = std::variant<bool>;
57     using PropertyMap = std::map<Property, Value>;
58 
59     using Interface = std::string;
60     using InterfaceMap = std::map<Interface, PropertyMap>;
61 
62     using Object = sdbusplus::message::object_path;
63     using ObjectMap = std::map<Object, InterfaceMap>;
64 
65   public:
66     Fan() = delete;
67     Fan(const Fan&) = delete;
68     Fan(Fan&&) = default;
69     Fan& operator=(const Fan&) = delete;
70     Fan& operator=(Fan&&) = default;
71     ~Fan() = default;
72 
73     /**
74      * @brief Constructor
75      *
76      * @param mode - mode of fan monitor
77      * @param bus - the dbus object
78      * @param event - event loop reference
79      * @param trust - the tach trust manager
80      * @param def - the fan definition structure
81      * @param system - Reference to the system object
82      */
83     Fan(Mode mode, sdbusplus::bus_t& bus, const sdeventplus::Event& event,
84         std::unique_ptr<trust::Manager>& trust, const FanDefinition& def,
85         System& system);
86 
87     /**
88      * @brief Callback function for when an input sensor changes
89      *
90      * Starts a timer, where if it expires then the sensor
91      * was out of range for too long and can be considered not functional.
92      */
93     void tachChanged(TachSensor& sensor);
94 
95     /**
96      * @brief Calls tachChanged(sensor) on each sensor
97      */
98     void tachChanged();
99 
100     /**
101      * @brief The callback function for the method
102      *
103      * Sets the sensor to not functional.
104      * If enough sensors are now not functional,
105      * updates the functional status of the whole
106      * fan in the inventory.
107      *
108      * @param[in] sensor - the sensor for state update
109      */
110     void updateState(TachSensor& sensor);
111 
112     /**
113      * @brief Get the name of the fan
114      *
115      * @return - The fan name
116      */
getName() const117     inline const std::string& getName() const
118     {
119         return _name;
120     }
121 
122     /**
123      * @brief Finds the target speed of this fan
124      *
125      * Finds the target speed from the list of sensors that make up this
126      * fan. At least one sensor should contain a target speed value.
127      *
128      * @return - The target speed found from the list of sensors on the fan
129      */
130     uint64_t findTargetSpeed();
131 
132     /**
133      * @brief Returns the contained TachSensor objects
134      *
135      * @return std::vector<std::shared_ptr<TachSensor>> - The sensors
136      */
sensors() const137     const std::vector<std::shared_ptr<TachSensor>>& sensors() const
138     {
139         return _sensors;
140     }
141 
142     /**
143      * @brief Returns the presence status of the fan
144      *
145      * @return bool - If the fan is present or not
146      */
present() const147     bool present() const
148     {
149         return _present;
150     }
151 
152     /**
153      * @brief Called from TachSensor when its error timer expires
154      *        so an event log calling out the fan can be created.
155      *
156      * @param[in] sensor - The nonfunctional sensor
157      */
158     void sensorErrorTimerExpired(const TachSensor& sensor);
159 
160     /**
161      * @brief Process the state of the given tach sensor without checking
162      * any trust groups the sensor may be included in
163      *
164      * @param[in] sensor - Tach sensor to process
165      *
166      * This function is intended to check the current state of a tach sensor
167      * regardless of whether or not the tach sensor is configured to be in any
168      * trust groups.
169      */
170     void process(TachSensor& sensor);
171 
172     /**
173      * @brief The function that runs when the power state changes
174      *
175      * @param[in] powerStateOn - If power is now on or not
176      */
177     void powerStateChanged(bool powerStateOn);
178 
179     /**
180      * @brief Timer callback function that deals with sensors using
181      *        the 'count' method for determining functional status.
182      *
183      * @param[in] sensor - TachSensor object
184      */
185     void countTimerExpired(TachSensor& sensor);
186 
187     /**
188      * @brief Returns the number of tach sensors (Sensor.Value ifaces)
189      *        on D-Bus at the last power on.
190      */
numSensorsOnDBusAtPowerOn() const191     inline size_t numSensorsOnDBusAtPowerOn() const
192     {
193         return _numSensorsOnDBusAtPowerOn;
194     }
195 
196     /**
197      * @brief Returns true if the sensor input is not within
198      * some deviation of the target.
199      *
200      * @param[in] sensor - the sensor to check
201      */
202     bool outOfRange(const TachSensor& sensor);
203 
204   private:
205     /**
206      * @brief Returns the number sensors that are nonfunctional
207      */
208     size_t countNonFunctionalSensors() const;
209 
210     /**
211      * @brief Updates the Functional property in the inventory
212      *        for the fan based on the value passed in.
213      *
214      * @param[in] functional - If the Functional property should
215      *                         be set to true or false.
216      *
217      * @return - True if an exception was encountered during update
218      */
219     bool updateInventory(bool functional);
220 
221     /**
222      * @brief Called by _monitorTimer to start fan monitoring some
223      *        amount of time after startup.
224      */
225     void startMonitor();
226 
227     /**
228      * @brief Called when the fan presence property changes on D-Bus
229      *
230      * @param[in] msg - The message from the propertiesChanged signal
231      */
232     void presenceChanged(sdbusplus::message_t& msg);
233 
234     /**
235      * @brief Called when there is an interfacesAdded signal on the
236      *        fan D-Bus path so the code can look for the 'Present'
237      *        property value.
238      *
239      * @param[in] msg - The message from the interfacesAdded signal
240      */
241     void presenceIfaceAdded(sdbusplus::message_t& msg);
242 
243     /**
244      * @brief the dbus object
245      */
246     sdbusplus::bus_t& _bus;
247 
248     /**
249      * @brief The inventory name of the fan
250      */
251     const std::string _name;
252 
253     /**
254      * @brief The percentage that the input speed must be below
255      *        the target speed to be considered an error.
256      *        Between 0 and 100.
257      */
258     const size_t _deviation;
259 
260     /**
261      * @brief The percentage that the input speed must be above
262      *        the target speed to be considered an error.
263      *        Between 0 and 100.
264      */
265     const size_t _upperDeviation;
266 
267     /**
268      * The number of sensors that must be nonfunctional at the
269      * same time in order for the fan to be set to nonfunctional
270      * in the inventory.
271      */
272     const size_t _numSensorFailsForNonFunc;
273 
274     /**
275      * The number of failed sensors
276      */
277     size_t _numFailedSensor = 0;
278 
279     /**
280      * @brief The current functional state of the fan
281      */
282     bool _functional = true;
283 
284     /**
285      * The sensor objects for the fan
286      */
287     std::vector<std::shared_ptr<TachSensor>> _sensors;
288 
289     /**
290      * The tach trust manager object
291      */
292     std::unique_ptr<trust::Manager>& _trustManager;
293 
294 #ifdef MONITOR_USE_JSON
295     /**
296      * @brief The number of seconds to wait after startup until
297      *        fan sensors should checked against their targets.
298      */
299     size_t _monitorDelay;
300 
301     /**
302      * @brief Expires after _monitorDelay to start fan monitoring.
303      */
304     sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> _monitorTimer;
305 #endif
306 
307     /**
308      * @brief Set to true when monitoring can start.
309      */
310     bool _monitorReady = false;
311 
312     /**
313      * @brief Reference to the System object
314      */
315     System& _system;
316 
317     /**
318      * @brief The match object for propertiesChanged signals
319      *        for the inventory item interface to track the
320      *        Present property.
321      */
322     sdbusplus::bus::match_t _presenceMatch;
323 
324     /**
325      * @brief The match object for the interfacesAdded signal
326      *        for the interface that has the Present property.
327      */
328     sdbusplus::bus::match_t _presenceIfaceAddedMatch;
329 
330     /**
331      * @brief The current presence state
332      */
333     bool _present = false;
334 
335     /**
336      * @brief The number of seconds to wait after a fan is removed before
337      *        creating an event log for it.  If std::nullopt, then no
338      *        event log will be created.
339      */
340     const std::optional<size_t> _fanMissingErrorDelay;
341 
342     /**
343      * @brief The timer that uses the _fanMissingErrorDelay timeout,
344      *        at the end of which an event log will be created.
345      */
346     std::unique_ptr<
347         sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>
348         _fanMissingErrorTimer;
349 
350     /**
351      * @brief If the fan and sensors should be set to functional when
352      *        a fan plug is detected.
353      */
354     bool _setFuncOnPresent;
355 
356     /**
357      * @brief The number of sensors that have their Sensor.Value interfaces
358      *        on D-Bus at the last power on.
359      *
360      * Will be zero until the power turns on the first time.
361      */
362     size_t _numSensorsOnDBusAtPowerOn = 0;
363 };
364 
365 } // namespace monitor
366 } // namespace fan
367 } // namespace phosphor
368