xref: /openbmc/phosphor-fan-presence/monitor/fan.hpp (revision edaeb31c886e2b8d2d43664ec4178c8d35094742)
1abf8da36SMatt Spinler #pragma once
2abf8da36SMatt Spinler 
3abf8da36SMatt Spinler #include <sdbusplus/bus.hpp>
4abf8da36SMatt Spinler #include <tuple>
5abf8da36SMatt Spinler #include <vector>
6e824f985SMatt Spinler #include "event.hpp"
7abf8da36SMatt Spinler #include "tach_sensor.hpp"
8abf8da36SMatt Spinler #include "types.hpp"
9abf8da36SMatt Spinler 
10abf8da36SMatt Spinler namespace phosphor
11abf8da36SMatt Spinler {
12abf8da36SMatt Spinler namespace fan
13abf8da36SMatt Spinler {
14abf8da36SMatt Spinler namespace monitor
15abf8da36SMatt Spinler {
16abf8da36SMatt Spinler 
17*edaeb31cSBrad Bishop /**
18*edaeb31cSBrad Bishop  * @class InvalidSensorError
19*edaeb31cSBrad Bishop  *
20*edaeb31cSBrad Bishop  * An exception type for sensors that don't exist or
21*edaeb31cSBrad Bishop  * are otherwise inaccessible.
22*edaeb31cSBrad Bishop  */
23*edaeb31cSBrad Bishop class InvalidSensorError : public std::exception {};
24abf8da36SMatt Spinler 
25abf8da36SMatt Spinler /**
26abf8da36SMatt Spinler  * @class Fan
27abf8da36SMatt Spinler  *
28abf8da36SMatt Spinler  * Represents a fan, which can contain 1 or more sensors which
29abf8da36SMatt Spinler  * loosely correspond to rotors.  See below.
30abf8da36SMatt Spinler  *
31abf8da36SMatt Spinler  * There is a sensor when hwmon exposes one, which means there is a
32abf8da36SMatt Spinler  * speed value to be read.  Sometimes there is a sensor per rotor,
33abf8da36SMatt Spinler  * and other times multiple rotors just use 1 sensor total where
34abf8da36SMatt Spinler  * the sensor reports the slowest speed of all of the rotors.
35abf8da36SMatt Spinler  *
36abf8da36SMatt Spinler  * A rotor's speed is set by writing the Target value of a sensor.
37abf8da36SMatt Spinler  * Sometimes each sensor in a fan supports having a Target, and other
38abf8da36SMatt Spinler  * times not all of them do.  A TachSensor object knows if it supports
39abf8da36SMatt Spinler  * the Target property.
40abf8da36SMatt Spinler  *
41abf8da36SMatt Spinler  * The strategy for monitoring fan speeds is as follows:
42abf8da36SMatt Spinler  *
43abf8da36SMatt Spinler  * Every time a Target (new speed written) or Input (actual speed read)
44abf8da36SMatt Spinler  * sensor changes, check if the input value is within some range of the target
45abf8da36SMatt Spinler  * value.  If it isn't, start a timer at the end of which the sensor will be
46abf8da36SMatt Spinler  * set to not functional.  If enough sensors in the fan are now nonfunctional,
47abf8da36SMatt Spinler  * set the whole fan to nonfunctional in the inventory.
48abf8da36SMatt Spinler  *
49abf8da36SMatt Spinler  * When sensor inputs come back within a specified range of the target,
50abf8da36SMatt Spinler  * stop its timer if running, make the sensor functional again if it wasn't,
51abf8da36SMatt Spinler  * and if enough sensors in the fan are now functional set the whole fan
52abf8da36SMatt Spinler  * back to functional in the inventory.
53abf8da36SMatt Spinler  */
54abf8da36SMatt Spinler class Fan
55abf8da36SMatt Spinler {
56b1e18514SMatt Spinler     using Property = std::string;
57b1e18514SMatt Spinler     using Value = sdbusplus::message::variant<bool>;
58b1e18514SMatt Spinler     using PropertyMap = std::map<Property, Value>;
59b1e18514SMatt Spinler 
60b1e18514SMatt Spinler     using Interface = std::string;
61b1e18514SMatt Spinler     using InterfaceMap = std::map<Interface, PropertyMap>;
62b1e18514SMatt Spinler 
63b1e18514SMatt Spinler     using Object = sdbusplus::message::object_path;
64b1e18514SMatt Spinler     using ObjectMap = std::map<Object, InterfaceMap>;
65abf8da36SMatt Spinler 
66abf8da36SMatt Spinler     public:
67abf8da36SMatt Spinler 
68abf8da36SMatt Spinler         Fan() = delete;
69abf8da36SMatt Spinler         Fan(const Fan&) = delete;
70abf8da36SMatt Spinler         Fan(Fan&&) = default;
71abf8da36SMatt Spinler         Fan& operator=(const Fan&) = delete;
72abf8da36SMatt Spinler         Fan& operator=(Fan&&) = default;
73abf8da36SMatt Spinler         ~Fan() = default;
74abf8da36SMatt Spinler 
75abf8da36SMatt Spinler         /**
76abf8da36SMatt Spinler          * @brief Constructor
77abf8da36SMatt Spinler          *
78abf8da36SMatt Spinler          * @param bus - the dbus object
79abf8da36SMatt Spinler          * @param events - pointer to sd_event object
80abf8da36SMatt Spinler          * @param def - the fan definition structure
81abf8da36SMatt Spinler          */
82abf8da36SMatt Spinler         Fan(sdbusplus::bus::bus& bus,
83e824f985SMatt Spinler             phosphor::fan::event::EventPtr& events,
84abf8da36SMatt Spinler             const FanDefinition& def);
85abf8da36SMatt Spinler 
86ebaae611SMatt Spinler         /**
87ebaae611SMatt Spinler          * @brief Callback function for when an input sensor changes
88ebaae611SMatt Spinler          *
89ebaae611SMatt Spinler          * Starts a timer, where if it expires then the sensor
90a9406a77SMatt Spinler          * was out of range for too long and can be considered not functional.
91ebaae611SMatt Spinler          */
92ebaae611SMatt Spinler         void tachChanged(TachSensor& sensor);
93ebaae611SMatt Spinler 
94ebaae611SMatt Spinler         /**
95ebaae611SMatt Spinler          * @brief Calls tachChanged(sensor) on each sensor
96ebaae611SMatt Spinler          */
97ebaae611SMatt Spinler         void tachChanged();
98abf8da36SMatt Spinler 
99a9406a77SMatt Spinler         /**
100a9406a77SMatt Spinler          * @brief The callback function for the timer
101a9406a77SMatt Spinler          *
102a9406a77SMatt Spinler          * Sets the sensor to not functional.
103a9406a77SMatt Spinler          * If enough sensors are now not functional,
104a9406a77SMatt Spinler          * updates the functional status of the whole
105a9406a77SMatt Spinler          * fan in the inventory.
106a9406a77SMatt Spinler          *
107a9406a77SMatt Spinler          * @param[in] sensor - the sensor whose timer expired
108a9406a77SMatt Spinler          */
109a9406a77SMatt Spinler         void timerExpired(TachSensor& sensor);
110a9406a77SMatt Spinler 
111abf8da36SMatt Spinler     private:
112abf8da36SMatt Spinler 
113abf8da36SMatt Spinler         /**
114abf8da36SMatt Spinler          * @brief Returns the target speed of the sensor
115abf8da36SMatt Spinler          *
116abf8da36SMatt Spinler          * If the sensor itself doesn't have a target, it finds
117abf8da36SMatt Spinler          * the target speed from another sensor.
118abf8da36SMatt Spinler          *
119abf8da36SMatt Spinler          * @param[in] sensor - the sensor to get the target speed for
120abf8da36SMatt Spinler          */
121abf8da36SMatt Spinler         uint64_t getTargetSpeed(const TachSensor& sensor);
122abf8da36SMatt Spinler 
123abf8da36SMatt Spinler         /**
124abf8da36SMatt Spinler          * @brief Returns true if the sensor input is not within
125abf8da36SMatt Spinler          * some deviation of the target.
126abf8da36SMatt Spinler          *
127abf8da36SMatt Spinler          * @param[in] sensor - the sensor to check
128abf8da36SMatt Spinler          */
129abf8da36SMatt Spinler         bool outOfRange(const TachSensor& sensor);
130abf8da36SMatt Spinler 
131abf8da36SMatt Spinler         /**
132abf8da36SMatt Spinler          * @brief Returns true if too many sensors are nonfunctional
133abf8da36SMatt Spinler          *        as defined by _numSensorFailsForNonFunc
134abf8da36SMatt Spinler          */
135abf8da36SMatt Spinler         bool tooManySensorsNonfunctional();
136abf8da36SMatt Spinler 
137b1e18514SMatt Spinler         /**
138b1e18514SMatt Spinler          * @brief Updates the Functional property in the inventory
139b1e18514SMatt Spinler          *        for the fan based on the value passed in.
140b1e18514SMatt Spinler          *
141b1e18514SMatt Spinler          * @param[in] functional - If the Functional property should
142b1e18514SMatt Spinler          *                         be set to true or false.
143b1e18514SMatt Spinler          */
144b1e18514SMatt Spinler         void updateInventory(bool functional);
145b1e18514SMatt Spinler 
146b1e18514SMatt Spinler         /**
147b1e18514SMatt Spinler          * @brief Returns the object map to use when updating the inventory
148b1e18514SMatt Spinler          *
149b1e18514SMatt Spinler          * @param[in] functional - If the Functional property should
150b1e18514SMatt Spinler          *                         be set to true or false.
151b1e18514SMatt Spinler          */
152b1e18514SMatt Spinler         ObjectMap getObjectMap(bool functional);
153abf8da36SMatt Spinler 
154abf8da36SMatt Spinler         /**
155abf8da36SMatt Spinler          * @brief the dbus object
156abf8da36SMatt Spinler          */
157abf8da36SMatt Spinler         sdbusplus::bus::bus& _bus;
158abf8da36SMatt Spinler 
159abf8da36SMatt Spinler         /**
160abf8da36SMatt Spinler          * @brief The inventory name of the fan
161abf8da36SMatt Spinler          */
162abf8da36SMatt Spinler         const std::string _name;
163abf8da36SMatt Spinler 
164abf8da36SMatt Spinler         /**
165abf8da36SMatt Spinler          * @brief The percentage that the input speed must be below
166abf8da36SMatt Spinler          *        the target speed to be considered an error.
167abf8da36SMatt Spinler          *        Between 0 and 100.
168abf8da36SMatt Spinler          */
169abf8da36SMatt Spinler         const size_t _deviation;
170abf8da36SMatt Spinler 
171abf8da36SMatt Spinler         /**
172abf8da36SMatt Spinler          * The number of sensors that must be nonfunctional at the
173abf8da36SMatt Spinler          * same time in order for the fan to be set to nonfunctional
174abf8da36SMatt Spinler          * in the inventory.
175abf8da36SMatt Spinler          */
176abf8da36SMatt Spinler         const size_t _numSensorFailsForNonFunc;
177abf8da36SMatt Spinler 
178abf8da36SMatt Spinler         /**
179abf8da36SMatt Spinler          * @brief The current functional state of the fan
180abf8da36SMatt Spinler          */
181abf8da36SMatt Spinler         bool _functional = true;
182abf8da36SMatt Spinler 
183abf8da36SMatt Spinler         /**
184abf8da36SMatt Spinler          * The sensor objects for the fan
185abf8da36SMatt Spinler          */
186abf8da36SMatt Spinler         std::vector<std::unique_ptr<TachSensor>> _sensors;
187abf8da36SMatt Spinler };
188abf8da36SMatt Spinler 
189abf8da36SMatt Spinler }
190abf8da36SMatt Spinler }
191abf8da36SMatt Spinler }
192