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