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