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