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