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