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