xref: /openbmc/phosphor-fan-presence/monitor/fan.hpp (revision f724c16b42abe061752f0d78f0bdb5e2c85de4b6)
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 /**
25abf8da36SMatt Spinler  * @class Fan
26abf8da36SMatt Spinler  *
27abf8da36SMatt Spinler  * Represents a fan, which can contain 1 or more sensors which
28abf8da36SMatt Spinler  * loosely correspond to rotors.  See below.
29abf8da36SMatt Spinler  *
30abf8da36SMatt Spinler  * There is a sensor when hwmon exposes one, which means there is a
31abf8da36SMatt Spinler  * speed value to be read.  Sometimes there is a sensor per rotor,
32abf8da36SMatt Spinler  * and other times multiple rotors just use 1 sensor total where
33abf8da36SMatt Spinler  * the sensor reports the slowest speed of all of the rotors.
34abf8da36SMatt Spinler  *
35abf8da36SMatt Spinler  * A rotor's speed is set by writing the Target value of a sensor.
36abf8da36SMatt Spinler  * Sometimes each sensor in a fan supports having a Target, and other
37abf8da36SMatt Spinler  * times not all of them do.  A TachSensor object knows if it supports
38abf8da36SMatt Spinler  * the Target property.
39abf8da36SMatt Spinler  *
40abf8da36SMatt Spinler  * The strategy for monitoring fan speeds is as follows:
41abf8da36SMatt Spinler  *
42abf8da36SMatt Spinler  * Every time a Target (new speed written) or Input (actual speed read)
43abf8da36SMatt Spinler  * sensor changes, check if the input value is within some range of the target
44abf8da36SMatt Spinler  * value.  If it isn't, start a timer at the end of which the sensor will be
45abf8da36SMatt Spinler  * set to not functional.  If enough sensors in the fan are now nonfunctional,
46abf8da36SMatt Spinler  * set the whole fan to nonfunctional in the inventory.
47abf8da36SMatt Spinler  *
48abf8da36SMatt Spinler  * When sensor inputs come back within a specified range of the target,
49abf8da36SMatt Spinler  * stop its timer if running, make the sensor functional again if it wasn't,
50abf8da36SMatt Spinler  * and if enough sensors in the fan are now functional set the whole fan
51abf8da36SMatt Spinler  * back to functional in the inventory.
52abf8da36SMatt Spinler  */
53abf8da36SMatt Spinler class Fan
54abf8da36SMatt Spinler {
55b1e18514SMatt Spinler     using Property = std::string;
56c21d0b36SPatrick Williams     using Value = std::variant<bool>;
57b1e18514SMatt Spinler     using PropertyMap = std::map<Property, Value>;
58b1e18514SMatt Spinler 
59b1e18514SMatt Spinler     using Interface = std::string;
60b1e18514SMatt Spinler     using InterfaceMap = std::map<Interface, PropertyMap>;
61b1e18514SMatt Spinler 
62b1e18514SMatt Spinler     using Object = sdbusplus::message::object_path;
63b1e18514SMatt Spinler     using ObjectMap = std::map<Object, InterfaceMap>;
64abf8da36SMatt Spinler 
65abf8da36SMatt Spinler   public:
66abf8da36SMatt Spinler     Fan() = delete;
67abf8da36SMatt Spinler     Fan(const Fan&) = delete;
68abf8da36SMatt Spinler     Fan(Fan&&) = default;
69abf8da36SMatt Spinler     Fan& operator=(const Fan&) = delete;
70abf8da36SMatt Spinler     Fan& operator=(Fan&&) = default;
71abf8da36SMatt Spinler     ~Fan() = default;
72abf8da36SMatt Spinler 
73abf8da36SMatt Spinler     /**
74abf8da36SMatt Spinler      * @brief Constructor
75abf8da36SMatt Spinler      *
766ad28430SMatthew Barth      * @param mode - mode of fan monitor
77abf8da36SMatt Spinler      * @param bus - the dbus object
781cfc2f11SWilliam A. Kennington III      * @param event - event loop reference
79c39e859bSMatt Spinler      * @param trust - the tach trust manager
80abf8da36SMatt Spinler      * @param def - the fan definition structure
81b0412d07SMatt Spinler      * @param system - Reference to the system object
82abf8da36SMatt Spinler      */
83cb356d48SPatrick Williams     Fan(Mode mode, sdbusplus::bus_t& bus, const sdeventplus::Event& event,
84b0412d07SMatt Spinler         std::unique_ptr<trust::Manager>& trust, const FanDefinition& def,
85b0412d07SMatt Spinler         System& system);
86abf8da36SMatt Spinler 
87ebaae611SMatt Spinler     /**
88ebaae611SMatt Spinler      * @brief Callback function for when an input sensor changes
89ebaae611SMatt Spinler      *
90ebaae611SMatt Spinler      * Starts a timer, where if it expires then the sensor
91a9406a77SMatt Spinler      * was out of range for too long and can be considered not functional.
92ebaae611SMatt Spinler      */
93ebaae611SMatt Spinler     void tachChanged(TachSensor& sensor);
94ebaae611SMatt Spinler 
95ebaae611SMatt Spinler     /**
96ebaae611SMatt Spinler      * @brief Calls tachChanged(sensor) on each sensor
97ebaae611SMatt Spinler      */
98ebaae611SMatt Spinler     void tachChanged();
99abf8da36SMatt Spinler 
100a9406a77SMatt Spinler     /**
10169f2f48eSJolie Ku      * @brief The callback function for the method
102a9406a77SMatt Spinler      *
103a9406a77SMatt Spinler      * Sets the sensor to not functional.
104a9406a77SMatt Spinler      * If enough sensors are now not functional,
105a9406a77SMatt Spinler      * updates the functional status of the whole
106a9406a77SMatt Spinler      * fan in the inventory.
107a9406a77SMatt Spinler      *
10869f2f48eSJolie Ku      * @param[in] sensor - the sensor for state update
109a9406a77SMatt Spinler      */
11069f2f48eSJolie Ku     void updateState(TachSensor& sensor);
111a9406a77SMatt Spinler 
1124d982856SMatthew Barth     /**
1134d982856SMatthew Barth      * @brief Get the name of the fan
1144d982856SMatthew Barth      *
1154d982856SMatthew Barth      * @return - The fan name
1164d982856SMatthew Barth      */
getName() const1174d982856SMatthew Barth     inline const std::string& getName() const
1184d982856SMatthew Barth     {
1194d982856SMatthew Barth         return _name;
1204d982856SMatthew Barth     }
1214d982856SMatthew Barth 
122f552ea5cSMatthew Barth     /**
123f552ea5cSMatthew Barth      * @brief Finds the target speed of this fan
124f552ea5cSMatthew Barth      *
125f552ea5cSMatthew Barth      * Finds the target speed from the list of sensors that make up this
126f552ea5cSMatthew Barth      * fan. At least one sensor should contain a target speed value.
127f552ea5cSMatthew Barth      *
128f552ea5cSMatthew Barth      * @return - The target speed found from the list of sensors on the fan
129f552ea5cSMatthew Barth      */
130f552ea5cSMatthew Barth     uint64_t findTargetSpeed();
131f552ea5cSMatthew Barth 
132b63aa09eSMatt Spinler     /**
133b63aa09eSMatt Spinler      * @brief Returns the contained TachSensor objects
134b63aa09eSMatt Spinler      *
135b63aa09eSMatt Spinler      * @return std::vector<std::shared_ptr<TachSensor>> - The sensors
136b63aa09eSMatt Spinler      */
sensors() const137b63aa09eSMatt Spinler     const std::vector<std::shared_ptr<TachSensor>>& sensors() const
138b63aa09eSMatt Spinler     {
139b63aa09eSMatt Spinler         return _sensors;
140b63aa09eSMatt Spinler     }
141b63aa09eSMatt Spinler 
142b63aa09eSMatt Spinler     /**
143b63aa09eSMatt Spinler      * @brief Returns the presence status of the fan
144b63aa09eSMatt Spinler      *
145b63aa09eSMatt Spinler      * @return bool - If the fan is present or not
146b63aa09eSMatt Spinler      */
present() const147b63aa09eSMatt Spinler     bool present() const
148b63aa09eSMatt Spinler     {
149b63aa09eSMatt Spinler         return _present;
150b63aa09eSMatt Spinler     }
151b63aa09eSMatt Spinler 
152f13b42e2SMatt Spinler     /**
153f13b42e2SMatt Spinler      * @brief Called from TachSensor when its error timer expires
154f13b42e2SMatt Spinler      *        so an event log calling out the fan can be created.
155f13b42e2SMatt Spinler      *
156f13b42e2SMatt Spinler      * @param[in] sensor - The nonfunctional sensor
157f13b42e2SMatt Spinler      */
158f13b42e2SMatt Spinler     void sensorErrorTimerExpired(const TachSensor& sensor);
159f13b42e2SMatt Spinler 
160fcb0dbcbSMatthew Barth     /**
161fcb0dbcbSMatthew Barth      * @brief Process the state of the given tach sensor without checking
162fcb0dbcbSMatthew Barth      * any trust groups the sensor may be included in
163fcb0dbcbSMatthew Barth      *
164fcb0dbcbSMatthew Barth      * @param[in] sensor - Tach sensor to process
165fcb0dbcbSMatthew Barth      *
166fcb0dbcbSMatthew Barth      * This function is intended to check the current state of a tach sensor
167fcb0dbcbSMatthew Barth      * regardless of whether or not the tach sensor is configured to be in any
168fcb0dbcbSMatthew Barth      * trust groups.
169fcb0dbcbSMatthew Barth      */
170fcb0dbcbSMatthew Barth     void process(TachSensor& sensor);
171fcb0dbcbSMatthew Barth 
1727d135641SMatt Spinler     /**
1737d135641SMatt Spinler      * @brief The function that runs when the power state changes
1747d135641SMatt Spinler      *
1757d135641SMatt Spinler      * @param[in] powerStateOn - If power is now on or not
1767d135641SMatt Spinler      */
1777d135641SMatt Spinler     void powerStateChanged(bool powerStateOn);
1787d135641SMatt Spinler 
179623635c6SMatt Spinler     /**
180623635c6SMatt Spinler      * @brief Timer callback function that deals with sensors using
181623635c6SMatt Spinler      *        the 'count' method for determining functional status.
182fdfcc679SMatt Spinler      *
183fdfcc679SMatt Spinler      * @param[in] sensor - TachSensor object
184623635c6SMatt Spinler      */
185fdfcc679SMatt Spinler     void countTimerExpired(TachSensor& sensor);
186623635c6SMatt Spinler 
187bb449c1cSMatt Spinler     /**
188bb449c1cSMatt Spinler      * @brief Returns the number of tach sensors (Sensor.Value ifaces)
189bb449c1cSMatt Spinler      *        on D-Bus at the last power on.
190bb449c1cSMatt Spinler      */
numSensorsOnDBusAtPowerOn() const191bb449c1cSMatt Spinler     inline size_t numSensorsOnDBusAtPowerOn() const
192bb449c1cSMatt Spinler     {
193bb449c1cSMatt Spinler         return _numSensorsOnDBusAtPowerOn;
194bb449c1cSMatt Spinler     }
195bb449c1cSMatt Spinler 
196abf8da36SMatt Spinler     /**
197abf8da36SMatt Spinler      * @brief Returns true if the sensor input is not within
198abf8da36SMatt Spinler      * some deviation of the target.
199abf8da36SMatt Spinler      *
200abf8da36SMatt Spinler      * @param[in] sensor - the sensor to check
201abf8da36SMatt Spinler      */
202abf8da36SMatt Spinler     bool outOfRange(const TachSensor& sensor);
203abf8da36SMatt Spinler 
204d16d464aSMatt Spinler   private:
205abf8da36SMatt Spinler     /**
2067c23a049SMatthew Barth      * @brief Returns the number sensors that are nonfunctional
207abf8da36SMatt Spinler      */
208ce6820abSMike Capps     size_t countNonFunctionalSensors() const;
209abf8da36SMatt Spinler 
210b1e18514SMatt Spinler     /**
211b1e18514SMatt Spinler      * @brief Updates the Functional property in the inventory
212b1e18514SMatt Spinler      *        for the fan based on the value passed in.
213b1e18514SMatt Spinler      *
214b1e18514SMatt Spinler      * @param[in] functional - If the Functional property should
215b1e18514SMatt Spinler      *                         be set to true or false.
2169ff48777SMike Capps      *
2179ff48777SMike Capps      * @return - True if an exception was encountered during update
218b1e18514SMatt Spinler      */
2199ff48777SMike Capps     bool updateInventory(bool functional);
220b1e18514SMatt Spinler 
221b1e18514SMatt Spinler     /**
222b0412d07SMatt Spinler      * @brief Called by _monitorTimer to start fan monitoring some
223b0412d07SMatt Spinler      *        amount of time after startup.
224b0412d07SMatt Spinler      */
225b0412d07SMatt Spinler     void startMonitor();
226b0412d07SMatt Spinler 
227b0412d07SMatt Spinler     /**
228b63aa09eSMatt Spinler      * @brief Called when the fan presence property changes on D-Bus
229b63aa09eSMatt Spinler      *
230b63aa09eSMatt Spinler      * @param[in] msg - The message from the propertiesChanged signal
231b63aa09eSMatt Spinler      */
232cb356d48SPatrick Williams     void presenceChanged(sdbusplus::message_t& msg);
233b63aa09eSMatt Spinler 
234b63aa09eSMatt Spinler     /**
2357d135641SMatt Spinler      * @brief Called when there is an interfacesAdded signal on the
2367d135641SMatt Spinler      *        fan D-Bus path so the code can look for the 'Present'
2377d135641SMatt Spinler      *        property value.
2387d135641SMatt Spinler      *
2397d135641SMatt Spinler      * @param[in] msg - The message from the interfacesAdded signal
2407d135641SMatt Spinler      */
241cb356d48SPatrick Williams     void presenceIfaceAdded(sdbusplus::message_t& msg);
2427d135641SMatt Spinler 
2437d135641SMatt Spinler     /**
244abf8da36SMatt Spinler      * @brief the dbus object
245abf8da36SMatt Spinler      */
246cb356d48SPatrick Williams     sdbusplus::bus_t& _bus;
247abf8da36SMatt Spinler 
248abf8da36SMatt Spinler     /**
249abf8da36SMatt Spinler      * @brief The inventory name of the fan
250abf8da36SMatt Spinler      */
251abf8da36SMatt Spinler     const std::string _name;
252abf8da36SMatt Spinler 
253abf8da36SMatt Spinler     /**
254abf8da36SMatt Spinler      * @brief The percentage that the input speed must be below
255abf8da36SMatt Spinler      *        the target speed to be considered an error.
256abf8da36SMatt Spinler      *        Between 0 and 100.
257abf8da36SMatt Spinler      */
258abf8da36SMatt Spinler     const size_t _deviation;
259abf8da36SMatt Spinler 
260abf8da36SMatt Spinler     /**
261*f724c16bSMatt Spinler      * @brief The percentage that the input speed must be above
262*f724c16bSMatt Spinler      *        the target speed to be considered an error.
263*f724c16bSMatt Spinler      *        Between 0 and 100.
264*f724c16bSMatt Spinler      */
265*f724c16bSMatt Spinler     const size_t _upperDeviation;
266*f724c16bSMatt Spinler 
267*f724c16bSMatt Spinler     /**
268abf8da36SMatt Spinler      * The number of sensors that must be nonfunctional at the
269abf8da36SMatt Spinler      * same time in order for the fan to be set to nonfunctional
270abf8da36SMatt Spinler      * in the inventory.
271abf8da36SMatt Spinler      */
272abf8da36SMatt Spinler     const size_t _numSensorFailsForNonFunc;
273abf8da36SMatt Spinler 
274abf8da36SMatt Spinler     /**
2755d564a9fSJolie Ku      * The number of failed sensors
2765d564a9fSJolie Ku      */
2775d564a9fSJolie Ku     size_t _numFailedSensor = 0;
2785d564a9fSJolie Ku 
2795d564a9fSJolie Ku     /**
280abf8da36SMatt Spinler      * @brief The current functional state of the fan
281abf8da36SMatt Spinler      */
282abf8da36SMatt Spinler     bool _functional = true;
283abf8da36SMatt Spinler 
284abf8da36SMatt Spinler     /**
285abf8da36SMatt Spinler      * The sensor objects for the fan
286abf8da36SMatt Spinler      */
28732affb98SMatthew Barth     std::vector<std::shared_ptr<TachSensor>> _sensors;
288c39e859bSMatt Spinler 
289c39e859bSMatt Spinler     /**
290c39e859bSMatt Spinler      * The tach trust manager object
291c39e859bSMatt Spinler      */
292c39e859bSMatt Spinler     std::unique_ptr<trust::Manager>& _trustManager;
293b0412d07SMatt Spinler 
294b0412d07SMatt Spinler #ifdef MONITOR_USE_JSON
295b0412d07SMatt Spinler     /**
296b0412d07SMatt Spinler      * @brief The number of seconds to wait after startup until
297b0412d07SMatt Spinler      *        fan sensors should checked against their targets.
298b0412d07SMatt Spinler      */
299b0412d07SMatt Spinler     size_t _monitorDelay;
300b0412d07SMatt Spinler 
301b0412d07SMatt Spinler     /**
302b0412d07SMatt Spinler      * @brief Expires after _monitorDelay to start fan monitoring.
303b0412d07SMatt Spinler      */
304b0412d07SMatt Spinler     sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> _monitorTimer;
305b0412d07SMatt Spinler #endif
306b0412d07SMatt Spinler 
307b0412d07SMatt Spinler     /**
308b0412d07SMatt Spinler      * @brief Set to true when monitoring can start.
309b0412d07SMatt Spinler      */
310b0412d07SMatt Spinler     bool _monitorReady = false;
311b0412d07SMatt Spinler 
312b0412d07SMatt Spinler     /**
313b0412d07SMatt Spinler      * @brief Reference to the System object
314b0412d07SMatt Spinler      */
315b0412d07SMatt Spinler     System& _system;
316b63aa09eSMatt Spinler 
317b63aa09eSMatt Spinler     /**
318b63aa09eSMatt Spinler      * @brief The match object for propertiesChanged signals
319b63aa09eSMatt Spinler      *        for the inventory item interface to track the
320b63aa09eSMatt Spinler      *        Present property.
321b63aa09eSMatt Spinler      */
322cb356d48SPatrick Williams     sdbusplus::bus::match_t _presenceMatch;
323b63aa09eSMatt Spinler 
324b63aa09eSMatt Spinler     /**
3257d135641SMatt Spinler      * @brief The match object for the interfacesAdded signal
3267d135641SMatt Spinler      *        for the interface that has the Present property.
3277d135641SMatt Spinler      */
328cb356d48SPatrick Williams     sdbusplus::bus::match_t _presenceIfaceAddedMatch;
3297d135641SMatt Spinler 
3307d135641SMatt Spinler     /**
331b63aa09eSMatt Spinler      * @brief The current presence state
332b63aa09eSMatt Spinler      */
333b63aa09eSMatt Spinler     bool _present = false;
33427f6b686SMatt Spinler 
33527f6b686SMatt Spinler     /**
33627f6b686SMatt Spinler      * @brief The number of seconds to wait after a fan is removed before
33727f6b686SMatt Spinler      *        creating an event log for it.  If std::nullopt, then no
33827f6b686SMatt Spinler      *        event log will be created.
33927f6b686SMatt Spinler      */
34027f6b686SMatt Spinler     const std::optional<size_t> _fanMissingErrorDelay;
34127f6b686SMatt Spinler 
34227f6b686SMatt Spinler     /**
34327f6b686SMatt Spinler      * @brief The timer that uses the _fanMissingErrorDelay timeout,
34427f6b686SMatt Spinler      *        at the end of which an event log will be created.
34527f6b686SMatt Spinler      */
34627f6b686SMatt Spinler     std::unique_ptr<
34727f6b686SMatt Spinler         sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>
34827f6b686SMatt Spinler         _fanMissingErrorTimer;
349623635c6SMatt Spinler 
350623635c6SMatt Spinler     /**
351a3584bd2SMatt Spinler      * @brief If the fan and sensors should be set to functional when
352a3584bd2SMatt Spinler      *        a fan plug is detected.
353a3584bd2SMatt Spinler      */
354a3584bd2SMatt Spinler     bool _setFuncOnPresent;
355bb449c1cSMatt Spinler 
356bb449c1cSMatt Spinler     /**
357bb449c1cSMatt Spinler      * @brief The number of sensors that have their Sensor.Value interfaces
358bb449c1cSMatt Spinler      *        on D-Bus at the last power on.
359bb449c1cSMatt Spinler      *
360bb449c1cSMatt Spinler      * Will be zero until the power turns on the first time.
361bb449c1cSMatt Spinler      */
362bb449c1cSMatt Spinler     size_t _numSensorsOnDBusAtPowerOn = 0;
363abf8da36SMatt Spinler };
364abf8da36SMatt Spinler 
365177fe986SMatthew Barth } // namespace monitor
366177fe986SMatthew Barth } // namespace fan
367177fe986SMatthew Barth } // namespace phosphor
368