blob: 75c2213605a56bc28f6ed0cc278fdb9cc18f2c15 [file] [log] [blame]
Matt Spinlerabf8da32017-04-27 14:08:45 -05001#pragma once
2
Matt Spinlerb0412d02020-10-12 16:53:52 -05003#include "config.h"
4
Matt Spinlerabf8da32017-04-27 14:08:45 -05005#include "tach_sensor.hpp"
Matt Spinlerc39e8592017-09-28 13:13:08 -05006#include "trust_manager.hpp"
Matt Spinlerabf8da32017-04-27 14:08:45 -05007#include "types.hpp"
8
Matthew Barth177fe982020-05-26 11:05:19 -05009#include <sdbusplus/bus.hpp>
10#include <sdeventplus/event.hpp>
11
12#include <tuple>
13#include <vector>
14
Matt Spinlerabf8da32017-04-27 14:08:45 -050015namespace phosphor
16{
17namespace fan
18{
19namespace monitor
20{
21
Matt Spinlerb0412d02020-10-12 16:53:52 -050022class System;
23
Brad Bishopedaeb312017-07-30 19:38:20 -040024/**
Matt Spinlerabf8da32017-04-27 14:08:45 -050025 * @class Fan
26 *
27 * Represents a fan, which can contain 1 or more sensors which
28 * loosely correspond to rotors. See below.
29 *
30 * There is a sensor when hwmon exposes one, which means there is a
31 * speed value to be read. Sometimes there is a sensor per rotor,
32 * and other times multiple rotors just use 1 sensor total where
33 * the sensor reports the slowest speed of all of the rotors.
34 *
35 * A rotor's speed is set by writing the Target value of a sensor.
36 * Sometimes each sensor in a fan supports having a Target, and other
37 * times not all of them do. A TachSensor object knows if it supports
38 * the Target property.
39 *
40 * The strategy for monitoring fan speeds is as follows:
41 *
42 * Every time a Target (new speed written) or Input (actual speed read)
43 * sensor changes, check if the input value is within some range of the target
44 * value. If it isn't, start a timer at the end of which the sensor will be
45 * set to not functional. If enough sensors in the fan are now nonfunctional,
46 * set the whole fan to nonfunctional in the inventory.
47 *
48 * When sensor inputs come back within a specified range of the target,
49 * stop its timer if running, make the sensor functional again if it wasn't,
50 * and if enough sensors in the fan are now functional set the whole fan
51 * back to functional in the inventory.
52 */
53class Fan
54{
Matt Spinlerb1e18512017-04-27 14:42:33 -050055 using Property = std::string;
Patrick Williamsc21d0b32020-05-13 17:55:14 -050056 using Value = std::variant<bool>;
Matt Spinlerb1e18512017-04-27 14:42:33 -050057 using PropertyMap = std::map<Property, Value>;
58
59 using Interface = std::string;
60 using InterfaceMap = std::map<Interface, PropertyMap>;
61
62 using Object = sdbusplus::message::object_path;
63 using ObjectMap = std::map<Object, InterfaceMap>;
Matt Spinlerabf8da32017-04-27 14:08:45 -050064
Matthew Barth177fe982020-05-26 11:05:19 -050065 public:
66 Fan() = delete;
67 Fan(const Fan&) = delete;
68 Fan(Fan&&) = default;
69 Fan& operator=(const Fan&) = delete;
70 Fan& operator=(Fan&&) = default;
71 ~Fan() = default;
Matt Spinlerabf8da32017-04-27 14:08:45 -050072
Matthew Barth177fe982020-05-26 11:05:19 -050073 /**
74 * @brief Constructor
75 *
76 * @param mode - mode of fan monitor
77 * @param bus - the dbus object
78 * @param event - event loop reference
79 * @param trust - the tach trust manager
80 * @param def - the fan definition structure
Matt Spinlerb0412d02020-10-12 16:53:52 -050081 * @param system - Reference to the system object
Matthew Barth177fe982020-05-26 11:05:19 -050082 */
Patrick Williamscb356d42022-07-22 19:26:53 -050083 Fan(Mode mode, sdbusplus::bus_t& bus, const sdeventplus::Event& event,
Matt Spinlerb0412d02020-10-12 16:53:52 -050084 std::unique_ptr<trust::Manager>& trust, const FanDefinition& def,
85 System& system);
Matt Spinlerabf8da32017-04-27 14:08:45 -050086
Matthew Barth177fe982020-05-26 11:05:19 -050087 /**
88 * @brief Callback function for when an input sensor changes
89 *
90 * Starts a timer, where if it expires then the sensor
91 * was out of range for too long and can be considered not functional.
92 */
93 void tachChanged(TachSensor& sensor);
Matt Spinlerabf8da32017-04-27 14:08:45 -050094
Matthew Barth177fe982020-05-26 11:05:19 -050095 /**
96 * @brief Calls tachChanged(sensor) on each sensor
97 */
98 void tachChanged();
Matt Spinlerebaae612017-04-27 14:21:48 -050099
Matthew Barth177fe982020-05-26 11:05:19 -0500100 /**
Jolie Ku69f2f482020-10-21 09:59:43 +0800101 * @brief The callback function for the method
Matthew Barth177fe982020-05-26 11:05:19 -0500102 *
103 * Sets the sensor to not functional.
104 * If enough sensors are now not functional,
105 * updates the functional status of the whole
106 * fan in the inventory.
107 *
Jolie Ku69f2f482020-10-21 09:59:43 +0800108 * @param[in] sensor - the sensor for state update
Matthew Barth177fe982020-05-26 11:05:19 -0500109 */
Jolie Ku69f2f482020-10-21 09:59:43 +0800110 void updateState(TachSensor& sensor);
Matt Spinlerabf8da32017-04-27 14:08:45 -0500111
Matthew Barth177fe982020-05-26 11:05:19 -0500112 /**
113 * @brief Get the name of the fan
114 *
115 * @return - The fan name
116 */
117 inline const std::string& getName() const
118 {
119 return _name;
120 }
Matt Spinlera9406a72017-04-27 14:29:24 -0500121
Matthew Barth177fe982020-05-26 11:05:19 -0500122 /**
123 * @brief Finds the target speed of this fan
124 *
125 * Finds the target speed from the list of sensors that make up this
126 * fan. At least one sensor should contain a target speed value.
127 *
128 * @return - The target speed found from the list of sensors on the fan
129 */
130 uint64_t findTargetSpeed();
Matthew Barth4d982852017-11-17 09:37:13 -0600131
Matt Spinlerb63aa092020-10-14 09:45:11 -0500132 /**
133 * @brief Returns the contained TachSensor objects
134 *
135 * @return std::vector<std::shared_ptr<TachSensor>> - The sensors
136 */
137 const std::vector<std::shared_ptr<TachSensor>>& sensors() const
138 {
139 return _sensors;
140 }
141
142 /**
143 * @brief Returns the presence status of the fan
144 *
145 * @return bool - If the fan is present or not
146 */
147 bool present() const
148 {
149 return _present;
150 }
151
Matt Spinlerf13b42e2020-10-26 15:29:49 -0500152 /**
153 * @brief Called from TachSensor when its error timer expires
154 * so an event log calling out the fan can be created.
155 *
156 * @param[in] sensor - The nonfunctional sensor
157 */
158 void sensorErrorTimerExpired(const TachSensor& sensor);
159
Matthew Barthfcb0dbc2021-02-10 14:23:39 -0600160 /**
161 * @brief Process the state of the given tach sensor without checking
162 * any trust groups the sensor may be included in
163 *
164 * @param[in] sensor - Tach sensor to process
165 *
166 * This function is intended to check the current state of a tach sensor
167 * regardless of whether or not the tach sensor is configured to be in any
168 * trust groups.
169 */
170 void process(TachSensor& sensor);
171
Matt Spinler7d135642021-02-04 12:44:17 -0600172 /**
173 * @brief The function that runs when the power state changes
174 *
175 * @param[in] powerStateOn - If power is now on or not
176 */
177 void powerStateChanged(bool powerStateOn);
178
Matt Spinler623635c2021-03-29 13:13:59 -0500179 /**
180 * @brief Timer callback function that deals with sensors using
181 * the 'count' method for determining functional status.
Matt Spinlerfdfcc672021-06-01 14:51:06 -0600182 *
183 * @param[in] sensor - TachSensor object
Matt Spinler623635c2021-03-29 13:13:59 -0500184 */
Matt Spinlerfdfcc672021-06-01 14:51:06 -0600185 void countTimerExpired(TachSensor& sensor);
Matt Spinler623635c2021-03-29 13:13:59 -0500186
Matt Spinlerbb449c12021-06-14 11:45:28 -0600187 /**
188 * @brief Returns the number of tach sensors (Sensor.Value ifaces)
189 * on D-Bus at the last power on.
190 */
191 inline size_t numSensorsOnDBusAtPowerOn() const
192 {
193 return _numSensorsOnDBusAtPowerOn;
194 }
195
Matthew Barth177fe982020-05-26 11:05:19 -0500196 /**
197 * @brief Returns true if the sensor input is not within
198 * some deviation of the target.
199 *
200 * @param[in] sensor - the sensor to check
201 */
202 bool outOfRange(const TachSensor& sensor);
Matthew Barthf552ea52018-01-15 16:22:04 -0600203
Matt Spinlerd16d4642022-08-26 13:32:07 -0500204 private:
Matthew Barth177fe982020-05-26 11:05:19 -0500205 /**
Matthew Barth7c23a042021-01-26 16:21:45 -0600206 * @brief Returns the number sensors that are nonfunctional
Matthew Barth177fe982020-05-26 11:05:19 -0500207 */
Mike Cappsce6820a2021-05-26 10:40:19 -0400208 size_t countNonFunctionalSensors() const;
Matt Spinlerabf8da32017-04-27 14:08:45 -0500209
Matthew Barth177fe982020-05-26 11:05:19 -0500210 /**
211 * @brief Updates the Functional property in the inventory
212 * for the fan based on the value passed in.
213 *
214 * @param[in] functional - If the Functional property should
215 * be set to true or false.
Mike Capps9ff48772021-07-19 14:49:43 -0400216 *
217 * @return - True if an exception was encountered during update
Matthew Barth177fe982020-05-26 11:05:19 -0500218 */
Mike Capps9ff48772021-07-19 14:49:43 -0400219 bool updateInventory(bool functional);
Matt Spinlerabf8da32017-04-27 14:08:45 -0500220
Matthew Barth177fe982020-05-26 11:05:19 -0500221 /**
Matt Spinlerb0412d02020-10-12 16:53:52 -0500222 * @brief Called by _monitorTimer to start fan monitoring some
223 * amount of time after startup.
224 */
225 void startMonitor();
226
227 /**
Matt Spinlerb63aa092020-10-14 09:45:11 -0500228 * @brief Called when the fan presence property changes on D-Bus
229 *
230 * @param[in] msg - The message from the propertiesChanged signal
231 */
Patrick Williamscb356d42022-07-22 19:26:53 -0500232 void presenceChanged(sdbusplus::message_t& msg);
Matt Spinlerb63aa092020-10-14 09:45:11 -0500233
234 /**
Matt Spinler7d135642021-02-04 12:44:17 -0600235 * @brief Called when there is an interfacesAdded signal on the
236 * fan D-Bus path so the code can look for the 'Present'
237 * property value.
238 *
239 * @param[in] msg - The message from the interfacesAdded signal
240 */
Patrick Williamscb356d42022-07-22 19:26:53 -0500241 void presenceIfaceAdded(sdbusplus::message_t& msg);
Matt Spinler7d135642021-02-04 12:44:17 -0600242
243 /**
Matthew Barth177fe982020-05-26 11:05:19 -0500244 * @brief the dbus object
245 */
Patrick Williamscb356d42022-07-22 19:26:53 -0500246 sdbusplus::bus_t& _bus;
Matt Spinlerabf8da32017-04-27 14:08:45 -0500247
Matthew Barth177fe982020-05-26 11:05:19 -0500248 /**
249 * @brief The inventory name of the fan
250 */
251 const std::string _name;
Matt Spinlerb1e18512017-04-27 14:42:33 -0500252
Matthew Barth177fe982020-05-26 11:05:19 -0500253 /**
254 * @brief The percentage that the input speed must be below
255 * the target speed to be considered an error.
256 * Between 0 and 100.
257 */
258 const size_t _deviation;
Matt Spinlerabf8da32017-04-27 14:08:45 -0500259
Matthew Barth177fe982020-05-26 11:05:19 -0500260 /**
261 * The number of sensors that must be nonfunctional at the
262 * same time in order for the fan to be set to nonfunctional
263 * in the inventory.
264 */
265 const size_t _numSensorFailsForNonFunc;
Matt Spinlerabf8da32017-04-27 14:08:45 -0500266
Matthew Barth177fe982020-05-26 11:05:19 -0500267 /**
Jolie Ku5d564a92020-10-23 09:04:28 +0800268 * The number of failed sensors
269 */
270 size_t _numFailedSensor = 0;
271
272 /**
Matthew Barth177fe982020-05-26 11:05:19 -0500273 * @brief The current functional state of the fan
274 */
275 bool _functional = true;
Matt Spinlerabf8da32017-04-27 14:08:45 -0500276
Matthew Barth177fe982020-05-26 11:05:19 -0500277 /**
278 * The sensor objects for the fan
279 */
280 std::vector<std::shared_ptr<TachSensor>> _sensors;
Matt Spinlerabf8da32017-04-27 14:08:45 -0500281
Matthew Barth177fe982020-05-26 11:05:19 -0500282 /**
283 * The tach trust manager object
284 */
285 std::unique_ptr<trust::Manager>& _trustManager;
Matt Spinlerb0412d02020-10-12 16:53:52 -0500286
287#ifdef MONITOR_USE_JSON
288 /**
289 * @brief The number of seconds to wait after startup until
290 * fan sensors should checked against their targets.
291 */
292 size_t _monitorDelay;
293
294 /**
295 * @brief Expires after _monitorDelay to start fan monitoring.
296 */
297 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> _monitorTimer;
298#endif
299
300 /**
301 * @brief Set to true when monitoring can start.
302 */
303 bool _monitorReady = false;
304
305 /**
306 * @brief Reference to the System object
307 */
308 System& _system;
Matt Spinlerb63aa092020-10-14 09:45:11 -0500309
310 /**
311 * @brief The match object for propertiesChanged signals
312 * for the inventory item interface to track the
313 * Present property.
314 */
Patrick Williamscb356d42022-07-22 19:26:53 -0500315 sdbusplus::bus::match_t _presenceMatch;
Matt Spinlerb63aa092020-10-14 09:45:11 -0500316
317 /**
Matt Spinler7d135642021-02-04 12:44:17 -0600318 * @brief The match object for the interfacesAdded signal
319 * for the interface that has the Present property.
320 */
Patrick Williamscb356d42022-07-22 19:26:53 -0500321 sdbusplus::bus::match_t _presenceIfaceAddedMatch;
Matt Spinler7d135642021-02-04 12:44:17 -0600322
323 /**
Matt Spinlerb63aa092020-10-14 09:45:11 -0500324 * @brief The current presence state
325 */
326 bool _present = false;
Matt Spinler27f6b682020-10-27 08:43:37 -0500327
328 /**
329 * @brief The number of seconds to wait after a fan is removed before
330 * creating an event log for it. If std::nullopt, then no
331 * event log will be created.
332 */
333 const std::optional<size_t> _fanMissingErrorDelay;
334
335 /**
336 * @brief The timer that uses the _fanMissingErrorDelay timeout,
337 * at the end of which an event log will be created.
338 */
339 std::unique_ptr<
340 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>
341 _fanMissingErrorTimer;
Matt Spinler623635c2021-03-29 13:13:59 -0500342
343 /**
Matt Spinlera3584bd2021-03-29 15:48:30 -0500344 * @brief If the fan and sensors should be set to functional when
345 * a fan plug is detected.
346 */
347 bool _setFuncOnPresent;
Matt Spinlerbb449c12021-06-14 11:45:28 -0600348
349 /**
350 * @brief The number of sensors that have their Sensor.Value interfaces
351 * on D-Bus at the last power on.
352 *
353 * Will be zero until the power turns on the first time.
354 */
355 size_t _numSensorsOnDBusAtPowerOn = 0;
Matt Spinlerabf8da32017-04-27 14:08:45 -0500356};
357
Matthew Barth177fe982020-05-26 11:05:19 -0500358} // namespace monitor
359} // namespace fan
360} // namespace phosphor