xref: /openbmc/phosphor-fan-presence/monitor/fan.hpp (revision b1e185141bdd6b25cea10627045d80e457105baf)
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 {
48*b1e18514SMatt Spinler     using Property = std::string;
49*b1e18514SMatt Spinler     using Value = sdbusplus::message::variant<bool>;
50*b1e18514SMatt Spinler     using PropertyMap = std::map<Property, Value>;
51*b1e18514SMatt Spinler 
52*b1e18514SMatt Spinler     using Interface = std::string;
53*b1e18514SMatt Spinler     using InterfaceMap = std::map<Interface, PropertyMap>;
54*b1e18514SMatt Spinler 
55*b1e18514SMatt Spinler     using Object = sdbusplus::message::object_path;
56*b1e18514SMatt Spinler     using ObjectMap = std::map<Object, InterfaceMap>;
57abf8da36SMatt Spinler 
58abf8da36SMatt Spinler     public:
59abf8da36SMatt Spinler 
60abf8da36SMatt Spinler         Fan() = delete;
61abf8da36SMatt Spinler         Fan(const Fan&) = delete;
62abf8da36SMatt Spinler         Fan(Fan&&) = default;
63abf8da36SMatt Spinler         Fan& operator=(const Fan&) = delete;
64abf8da36SMatt Spinler         Fan& operator=(Fan&&) = default;
65abf8da36SMatt Spinler         ~Fan() = default;
66abf8da36SMatt Spinler 
67abf8da36SMatt Spinler         /**
68abf8da36SMatt Spinler          * @brief Constructor
69abf8da36SMatt Spinler          *
70abf8da36SMatt Spinler          * @param bus - the dbus object
71abf8da36SMatt Spinler          * @param events - pointer to sd_event object
72abf8da36SMatt Spinler          * @param def - the fan definition structure
73abf8da36SMatt Spinler          */
74abf8da36SMatt Spinler         Fan(sdbusplus::bus::bus& bus,
75abf8da36SMatt Spinler             std::shared_ptr<sd_event>& events,
76abf8da36SMatt Spinler             const FanDefinition& def);
77abf8da36SMatt Spinler 
78ebaae611SMatt Spinler         /**
79ebaae611SMatt Spinler          * @brief Callback function for when an input sensor changes
80ebaae611SMatt Spinler          *
81ebaae611SMatt Spinler          * Starts a timer, where if it expires then the sensor
82a9406a77SMatt Spinler          * was out of range for too long and can be considered not functional.
83ebaae611SMatt Spinler          */
84ebaae611SMatt Spinler         void tachChanged(TachSensor& sensor);
85ebaae611SMatt Spinler 
86ebaae611SMatt Spinler         /**
87ebaae611SMatt Spinler          * @brief Calls tachChanged(sensor) on each sensor
88ebaae611SMatt Spinler          */
89ebaae611SMatt Spinler         void tachChanged();
90abf8da36SMatt Spinler 
91a9406a77SMatt Spinler         /**
92a9406a77SMatt Spinler          * @brief The callback function for the timer
93a9406a77SMatt Spinler          *
94a9406a77SMatt Spinler          * Sets the sensor to not functional.
95a9406a77SMatt Spinler          * If enough sensors are now not functional,
96a9406a77SMatt Spinler          * updates the functional status of the whole
97a9406a77SMatt Spinler          * fan in the inventory.
98a9406a77SMatt Spinler          *
99a9406a77SMatt Spinler          * @param[in] sensor - the sensor whose timer expired
100a9406a77SMatt Spinler          */
101a9406a77SMatt Spinler         void timerExpired(TachSensor& sensor);
102a9406a77SMatt Spinler 
103abf8da36SMatt Spinler     private:
104abf8da36SMatt Spinler 
105abf8da36SMatt Spinler         /**
106abf8da36SMatt Spinler          * @brief Returns the target speed of the sensor
107abf8da36SMatt Spinler          *
108abf8da36SMatt Spinler          * If the sensor itself doesn't have a target, it finds
109abf8da36SMatt Spinler          * the target speed from another sensor.
110abf8da36SMatt Spinler          *
111abf8da36SMatt Spinler          * @param[in] sensor - the sensor to get the target speed for
112abf8da36SMatt Spinler          */
113abf8da36SMatt Spinler         uint64_t getTargetSpeed(const TachSensor& sensor);
114abf8da36SMatt Spinler 
115abf8da36SMatt Spinler         /**
116abf8da36SMatt Spinler          * @brief Returns true if the sensor input is not within
117abf8da36SMatt Spinler          * some deviation of the target.
118abf8da36SMatt Spinler          *
119abf8da36SMatt Spinler          * @param[in] sensor - the sensor to check
120abf8da36SMatt Spinler          */
121abf8da36SMatt Spinler         bool outOfRange(const TachSensor& sensor);
122abf8da36SMatt Spinler 
123abf8da36SMatt Spinler         /**
124abf8da36SMatt Spinler          * @brief Returns true if too many sensors are nonfunctional
125abf8da36SMatt Spinler          *        as defined by _numSensorFailsForNonFunc
126abf8da36SMatt Spinler          */
127abf8da36SMatt Spinler         bool tooManySensorsNonfunctional();
128abf8da36SMatt Spinler 
129*b1e18514SMatt Spinler         /**
130*b1e18514SMatt Spinler          * @brief Updates the Functional property in the inventory
131*b1e18514SMatt Spinler          *        for the fan based on the value passed in.
132*b1e18514SMatt Spinler          *
133*b1e18514SMatt Spinler          * @param[in] functional - If the Functional property should
134*b1e18514SMatt Spinler          *                         be set to true or false.
135*b1e18514SMatt Spinler          */
136*b1e18514SMatt Spinler         void updateInventory(bool functional);
137*b1e18514SMatt Spinler 
138*b1e18514SMatt Spinler         /**
139*b1e18514SMatt Spinler          * @brief Returns the object map to use when updating the inventory
140*b1e18514SMatt Spinler          *
141*b1e18514SMatt Spinler          * @param[in] functional - If the Functional property should
142*b1e18514SMatt Spinler          *                         be set to true or false.
143*b1e18514SMatt Spinler          */
144*b1e18514SMatt Spinler         ObjectMap getObjectMap(bool functional);
145abf8da36SMatt Spinler 
146abf8da36SMatt Spinler         /**
147abf8da36SMatt Spinler          * @brief the dbus object
148abf8da36SMatt Spinler          */
149abf8da36SMatt Spinler         sdbusplus::bus::bus& _bus;
150abf8da36SMatt Spinler 
151abf8da36SMatt Spinler         /**
152abf8da36SMatt Spinler          * @brief The inventory name of the fan
153abf8da36SMatt Spinler          */
154abf8da36SMatt Spinler         const std::string _name;
155abf8da36SMatt Spinler 
156abf8da36SMatt Spinler         /**
157abf8da36SMatt Spinler          * @brief The percentage that the input speed must be below
158abf8da36SMatt Spinler          *        the target speed to be considered an error.
159abf8da36SMatt Spinler          *        Between 0 and 100.
160abf8da36SMatt Spinler          */
161abf8da36SMatt Spinler         const size_t _deviation;
162abf8da36SMatt Spinler 
163abf8da36SMatt Spinler         /**
164abf8da36SMatt Spinler          * The number of sensors that must be nonfunctional at the
165abf8da36SMatt Spinler          * same time in order for the fan to be set to nonfunctional
166abf8da36SMatt Spinler          * in the inventory.
167abf8da36SMatt Spinler          */
168abf8da36SMatt Spinler         const size_t _numSensorFailsForNonFunc;
169abf8da36SMatt Spinler 
170abf8da36SMatt Spinler         /**
171abf8da36SMatt Spinler          * @brief The current functional state of the fan
172abf8da36SMatt Spinler          */
173abf8da36SMatt Spinler         bool _functional = true;
174abf8da36SMatt Spinler 
175abf8da36SMatt Spinler         /**
176abf8da36SMatt Spinler          * The sensor objects for the fan
177abf8da36SMatt Spinler          */
178abf8da36SMatt Spinler         std::vector<std::unique_ptr<TachSensor>> _sensors;
179abf8da36SMatt Spinler };
180abf8da36SMatt Spinler 
181abf8da36SMatt Spinler }
182abf8da36SMatt Spinler }
183abf8da36SMatt Spinler }
184