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