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