xref: /openbmc/phosphor-fan-presence/monitor/fan.hpp (revision ebaae6115ff5248d7f46d065ca96229c1f4e583d)
1abf8da36SMatt Spinler #pragma once
2abf8da36SMatt Spinler 
3abf8da36SMatt Spinler #include <sdbusplus/bus.hpp>
4abf8da36SMatt Spinler #include <tuple>
5abf8da36SMatt Spinler #include <vector>
6abf8da36SMatt Spinler #include "tach_sensor.hpp"
7abf8da36SMatt Spinler #include "types.hpp"
8abf8da36SMatt Spinler 
9abf8da36SMatt Spinler namespace phosphor
10abf8da36SMatt Spinler {
11abf8da36SMatt Spinler namespace fan
12abf8da36SMatt Spinler {
13abf8da36SMatt Spinler namespace monitor
14abf8da36SMatt Spinler {
15abf8da36SMatt Spinler 
16abf8da36SMatt Spinler 
17abf8da36SMatt Spinler /**
18abf8da36SMatt Spinler  * @class Fan
19abf8da36SMatt Spinler  *
20abf8da36SMatt Spinler  * Represents a fan, which can contain 1 or more sensors which
21abf8da36SMatt Spinler  * loosely correspond to rotors.  See below.
22abf8da36SMatt Spinler  *
23abf8da36SMatt Spinler  * There is a sensor when hwmon exposes one, which means there is a
24abf8da36SMatt Spinler  * speed value to be read.  Sometimes there is a sensor per rotor,
25abf8da36SMatt Spinler  * and other times multiple rotors just use 1 sensor total where
26abf8da36SMatt Spinler  * the sensor reports the slowest speed of all of the rotors.
27abf8da36SMatt Spinler  *
28abf8da36SMatt Spinler  * A rotor's speed is set by writing the Target value of a sensor.
29abf8da36SMatt Spinler  * Sometimes each sensor in a fan supports having a Target, and other
30abf8da36SMatt Spinler  * times not all of them do.  A TachSensor object knows if it supports
31abf8da36SMatt Spinler  * the Target property.
32abf8da36SMatt Spinler  *
33abf8da36SMatt Spinler  * The strategy for monitoring fan speeds is as follows:
34abf8da36SMatt Spinler  *
35abf8da36SMatt Spinler  * Every time a Target (new speed written) or Input (actual speed read)
36abf8da36SMatt Spinler  * sensor changes, check if the input value is within some range of the target
37abf8da36SMatt Spinler  * value.  If it isn't, start a timer at the end of which the sensor will be
38abf8da36SMatt Spinler  * set to not functional.  If enough sensors in the fan are now nonfunctional,
39abf8da36SMatt Spinler  * set the whole fan to nonfunctional in the inventory.
40abf8da36SMatt Spinler  *
41abf8da36SMatt Spinler  * When sensor inputs come back within a specified range of the target,
42abf8da36SMatt Spinler  * stop its timer if running, make the sensor functional again if it wasn't,
43abf8da36SMatt Spinler  * and if enough sensors in the fan are now functional set the whole fan
44abf8da36SMatt Spinler  * back to functional in the inventory.
45abf8da36SMatt Spinler  */
46abf8da36SMatt Spinler class Fan
47abf8da36SMatt Spinler {
48abf8da36SMatt Spinler 
49abf8da36SMatt Spinler     public:
50abf8da36SMatt Spinler 
51abf8da36SMatt Spinler         Fan() = delete;
52abf8da36SMatt Spinler         Fan(const Fan&) = delete;
53abf8da36SMatt Spinler         Fan(Fan&&) = default;
54abf8da36SMatt Spinler         Fan& operator=(const Fan&) = delete;
55abf8da36SMatt Spinler         Fan& operator=(Fan&&) = default;
56abf8da36SMatt Spinler         ~Fan() = default;
57abf8da36SMatt Spinler 
58abf8da36SMatt Spinler         /**
59abf8da36SMatt Spinler          * @brief Constructor
60abf8da36SMatt Spinler          *
61abf8da36SMatt Spinler          * @param bus - the dbus object
62abf8da36SMatt Spinler          * @param events - pointer to sd_event object
63abf8da36SMatt Spinler          * @param def - the fan definition structure
64abf8da36SMatt Spinler          */
65abf8da36SMatt Spinler         Fan(sdbusplus::bus::bus& bus,
66abf8da36SMatt Spinler             std::shared_ptr<sd_event>& events,
67abf8da36SMatt Spinler             const FanDefinition& def);
68abf8da36SMatt Spinler 
69*ebaae611SMatt Spinler         /**
70*ebaae611SMatt Spinler          * @brief Callback function for when an input sensor changes
71*ebaae611SMatt Spinler          *
72*ebaae611SMatt Spinler          * Starts a timer, where if it expires then the sensor
73*ebaae611SMatt Spinler          * was slow for too long and can be considered not functional.
74*ebaae611SMatt Spinler          */
75*ebaae611SMatt Spinler         void tachChanged(TachSensor& sensor);
76*ebaae611SMatt Spinler 
77*ebaae611SMatt Spinler         /**
78*ebaae611SMatt Spinler          * @brief Calls tachChanged(sensor) on each sensor
79*ebaae611SMatt Spinler          */
80*ebaae611SMatt Spinler         void tachChanged();
81abf8da36SMatt Spinler 
82abf8da36SMatt Spinler     private:
83abf8da36SMatt Spinler 
84abf8da36SMatt Spinler         /**
85abf8da36SMatt Spinler          * @brief Returns the target speed of the sensor
86abf8da36SMatt Spinler          *
87abf8da36SMatt Spinler          * If the sensor itself doesn't have a target, it finds
88abf8da36SMatt Spinler          * the target speed from another sensor.
89abf8da36SMatt Spinler          *
90abf8da36SMatt Spinler          * @param[in] sensor - the sensor to get the target speed for
91abf8da36SMatt Spinler          */
92abf8da36SMatt Spinler         uint64_t getTargetSpeed(const TachSensor& sensor);
93abf8da36SMatt Spinler 
94abf8da36SMatt Spinler         /**
95abf8da36SMatt Spinler          * @brief Returns true if the sensor input is not within
96abf8da36SMatt Spinler          * some deviation of the target.
97abf8da36SMatt Spinler          *
98abf8da36SMatt Spinler          * @param[in] sensor - the sensor to check
99abf8da36SMatt Spinler          */
100abf8da36SMatt Spinler         bool outOfRange(const TachSensor& sensor);
101abf8da36SMatt Spinler 
102abf8da36SMatt Spinler         /**
103abf8da36SMatt Spinler          * @brief Returns true if too many sensors are nonfunctional
104abf8da36SMatt Spinler          *        as defined by _numSensorFailsForNonFunc
105abf8da36SMatt Spinler          */
106abf8da36SMatt Spinler         bool tooManySensorsNonfunctional();
107abf8da36SMatt Spinler 
108abf8da36SMatt Spinler 
109abf8da36SMatt Spinler         /**
110abf8da36SMatt Spinler          * @brief the dbus object
111abf8da36SMatt Spinler          */
112abf8da36SMatt Spinler         sdbusplus::bus::bus& _bus;
113abf8da36SMatt Spinler 
114abf8da36SMatt Spinler         /**
115abf8da36SMatt Spinler          * @brief The inventory name of the fan
116abf8da36SMatt Spinler          */
117abf8da36SMatt Spinler         const std::string _name;
118abf8da36SMatt Spinler 
119abf8da36SMatt Spinler         /**
120abf8da36SMatt Spinler          * @brief The percentage that the input speed must be below
121abf8da36SMatt Spinler          *        the target speed to be considered an error.
122abf8da36SMatt Spinler          *        Between 0 and 100.
123abf8da36SMatt Spinler          */
124abf8da36SMatt Spinler         const size_t _deviation;
125abf8da36SMatt Spinler 
126abf8da36SMatt Spinler         /**
127abf8da36SMatt Spinler          * The number of sensors that must be nonfunctional at the
128abf8da36SMatt Spinler          * same time in order for the fan to be set to nonfunctional
129abf8da36SMatt Spinler          * in the inventory.
130abf8da36SMatt Spinler          */
131abf8da36SMatt Spinler         const size_t _numSensorFailsForNonFunc;
132abf8da36SMatt Spinler 
133abf8da36SMatt Spinler         /**
134abf8da36SMatt Spinler          * @brief The current functional state of the fan
135abf8da36SMatt Spinler          */
136abf8da36SMatt Spinler         bool _functional = true;
137abf8da36SMatt Spinler 
138abf8da36SMatt Spinler         /**
139abf8da36SMatt Spinler          * The sensor objects for the fan
140abf8da36SMatt Spinler          */
141abf8da36SMatt Spinler         std::vector<std::unique_ptr<TachSensor>> _sensors;
142abf8da36SMatt Spinler };
143abf8da36SMatt Spinler 
144abf8da36SMatt Spinler }
145abf8da36SMatt Spinler }
146abf8da36SMatt Spinler }
147