blob: 3da75cf9a3a4c38271e61c32394f64d71719c111 [file] [log] [blame]
Matt Spinlerabf8da32017-04-27 14:08:45 -05001#pragma once
2
3#include <sdbusplus/bus.hpp>
4#include <tuple>
5#include <vector>
Matt Spinlere824f982017-05-11 10:07:55 -05006#include "event.hpp"
Matt Spinlerabf8da32017-04-27 14:08:45 -05007#include "tach_sensor.hpp"
8#include "types.hpp"
9
10namespace phosphor
11{
12namespace fan
13{
14namespace monitor
15{
16
Brad Bishopedaeb312017-07-30 19:38:20 -040017/**
Matthew Barth6ad28432017-08-22 11:18:19 -050018 * The mode fan monitor will run in:
19 * - init - only do the initialization steps
20 * - monitor - run normal monitoring algorithm
21 */
22enum class Mode
23{
24 init,
25 monitor
26};
27
28/**
Brad Bishopedaeb312017-07-30 19:38:20 -040029 * @class InvalidSensorError
30 *
31 * An exception type for sensors that don't exist or
32 * are otherwise inaccessible.
33 */
34class InvalidSensorError : public std::exception {};
Matt Spinlerabf8da32017-04-27 14:08:45 -050035
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 */
65class Fan
66{
Matt Spinlerb1e18512017-04-27 14:42:33 -050067 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>;
Matt Spinlerabf8da32017-04-27 14:08:45 -050076
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 *
Matthew Barth6ad28432017-08-22 11:18:19 -050089 * @param mode - mode of fan monitor
Matt Spinlerabf8da32017-04-27 14:08:45 -050090 * @param bus - the dbus object
91 * @param events - pointer to sd_event object
92 * @param def - the fan definition structure
93 */
Matthew Barth6ad28432017-08-22 11:18:19 -050094 Fan(Mode mode,
95 sdbusplus::bus::bus& bus,
Matt Spinlere824f982017-05-11 10:07:55 -050096 phosphor::fan::event::EventPtr& events,
Matt Spinlerabf8da32017-04-27 14:08:45 -050097 const FanDefinition& def);
98
Matt Spinlerebaae612017-04-27 14:21:48 -050099 /**
100 * @brief Callback function for when an input sensor changes
101 *
102 * Starts a timer, where if it expires then the sensor
Matt Spinlera9406a72017-04-27 14:29:24 -0500103 * was out of range for too long and can be considered not functional.
Matt Spinlerebaae612017-04-27 14:21:48 -0500104 */
105 void tachChanged(TachSensor& sensor);
106
107 /**
108 * @brief Calls tachChanged(sensor) on each sensor
109 */
110 void tachChanged();
Matt Spinlerabf8da32017-04-27 14:08:45 -0500111
Matt Spinlera9406a72017-04-27 14:29:24 -0500112 /**
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
Matt Spinlerabf8da32017-04-27 14:08:45 -0500124 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
Matt Spinlerb1e18512017-04-27 14:42:33 -0500150 /**
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);
Matt Spinlerabf8da32017-04-27 14:08:45 -0500166
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}