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