| Matt Spinler | abf8da3 | 2017-04-27 14:08:45 -0500 | [diff] [blame] | 1 | #pragma once | 
 | 2 |  | 
| Matt Spinler | b0412d0 | 2020-10-12 16:53:52 -0500 | [diff] [blame] | 3 | #include "config.h" | 
 | 4 |  | 
| Matt Spinler | abf8da3 | 2017-04-27 14:08:45 -0500 | [diff] [blame] | 5 | #include "tach_sensor.hpp" | 
| Matt Spinler | c39e859 | 2017-09-28 13:13:08 -0500 | [diff] [blame] | 6 | #include "trust_manager.hpp" | 
| Matt Spinler | abf8da3 | 2017-04-27 14:08:45 -0500 | [diff] [blame] | 7 | #include "types.hpp" | 
 | 8 |  | 
| Matthew Barth | 177fe98 | 2020-05-26 11:05:19 -0500 | [diff] [blame] | 9 | #include <sdbusplus/bus.hpp> | 
 | 10 | #include <sdeventplus/event.hpp> | 
 | 11 |  | 
 | 12 | #include <tuple> | 
 | 13 | #include <vector> | 
 | 14 |  | 
| Matt Spinler | abf8da3 | 2017-04-27 14:08:45 -0500 | [diff] [blame] | 15 | namespace phosphor | 
 | 16 | { | 
 | 17 | namespace fan | 
 | 18 | { | 
 | 19 | namespace monitor | 
 | 20 | { | 
 | 21 |  | 
| Matt Spinler | b0412d0 | 2020-10-12 16:53:52 -0500 | [diff] [blame] | 22 | class System; | 
 | 23 |  | 
| Brad Bishop | edaeb31 | 2017-07-30 19:38:20 -0400 | [diff] [blame] | 24 | /** | 
| Matt Spinler | abf8da3 | 2017-04-27 14:08:45 -0500 | [diff] [blame] | 25 |  * @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 |  */ | 
 | 53 | class Fan | 
 | 54 | { | 
| Matt Spinler | b1e1851 | 2017-04-27 14:42:33 -0500 | [diff] [blame] | 55 |     using Property = std::string; | 
| Patrick Williams | c21d0b3 | 2020-05-13 17:55:14 -0500 | [diff] [blame] | 56 |     using Value = std::variant<bool>; | 
| Matt Spinler | b1e1851 | 2017-04-27 14:42:33 -0500 | [diff] [blame] | 57 |     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 Spinler | abf8da3 | 2017-04-27 14:08:45 -0500 | [diff] [blame] | 64 |  | 
| Matthew Barth | 177fe98 | 2020-05-26 11:05:19 -0500 | [diff] [blame] | 65 |   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 Spinler | abf8da3 | 2017-04-27 14:08:45 -0500 | [diff] [blame] | 72 |  | 
| Matthew Barth | 177fe98 | 2020-05-26 11:05:19 -0500 | [diff] [blame] | 73 |     /** | 
 | 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 Spinler | b0412d0 | 2020-10-12 16:53:52 -0500 | [diff] [blame] | 81 |      * @param system - Reference to the system object | 
| Matthew Barth | 177fe98 | 2020-05-26 11:05:19 -0500 | [diff] [blame] | 82 |      */ | 
 | 83 |     Fan(Mode mode, sdbusplus::bus::bus& bus, const sdeventplus::Event& event, | 
| Matt Spinler | b0412d0 | 2020-10-12 16:53:52 -0500 | [diff] [blame] | 84 |         std::unique_ptr<trust::Manager>& trust, const FanDefinition& def, | 
 | 85 |         System& system); | 
| Matt Spinler | abf8da3 | 2017-04-27 14:08:45 -0500 | [diff] [blame] | 86 |  | 
| Matthew Barth | 177fe98 | 2020-05-26 11:05:19 -0500 | [diff] [blame] | 87 |     /** | 
 | 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 Spinler | abf8da3 | 2017-04-27 14:08:45 -0500 | [diff] [blame] | 94 |  | 
| Matthew Barth | 177fe98 | 2020-05-26 11:05:19 -0500 | [diff] [blame] | 95 |     /** | 
 | 96 |      * @brief Calls tachChanged(sensor) on each sensor | 
 | 97 |      */ | 
 | 98 |     void tachChanged(); | 
| Matt Spinler | ebaae61 | 2017-04-27 14:21:48 -0500 | [diff] [blame] | 99 |  | 
| Matthew Barth | 177fe98 | 2020-05-26 11:05:19 -0500 | [diff] [blame] | 100 |     /** | 
| Jolie Ku | 69f2f48 | 2020-10-21 09:59:43 +0800 | [diff] [blame] | 101 |      * @brief The callback function for the method | 
| Matthew Barth | 177fe98 | 2020-05-26 11:05:19 -0500 | [diff] [blame] | 102 |      * | 
 | 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 Ku | 69f2f48 | 2020-10-21 09:59:43 +0800 | [diff] [blame] | 108 |      * @param[in] sensor - the sensor for state update | 
| Matthew Barth | 177fe98 | 2020-05-26 11:05:19 -0500 | [diff] [blame] | 109 |      */ | 
| Jolie Ku | 69f2f48 | 2020-10-21 09:59:43 +0800 | [diff] [blame] | 110 |     void updateState(TachSensor& sensor); | 
| Matt Spinler | abf8da3 | 2017-04-27 14:08:45 -0500 | [diff] [blame] | 111 |  | 
| Matthew Barth | 177fe98 | 2020-05-26 11:05:19 -0500 | [diff] [blame] | 112 |     /** | 
 | 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 Spinler | a9406a7 | 2017-04-27 14:29:24 -0500 | [diff] [blame] | 121 |  | 
| Matthew Barth | 177fe98 | 2020-05-26 11:05:19 -0500 | [diff] [blame] | 122 |     /** | 
 | 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 Barth | 4d98285 | 2017-11-17 09:37:13 -0600 | [diff] [blame] | 131 |  | 
| Matt Spinler | b63aa09 | 2020-10-14 09:45:11 -0500 | [diff] [blame] | 132 |     /** | 
 | 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 Spinler | f13b42e | 2020-10-26 15:29:49 -0500 | [diff] [blame] | 152 |     /** | 
 | 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 Barth | fcb0dbc | 2021-02-10 14:23:39 -0600 | [diff] [blame] | 160 |     /** | 
 | 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 Spinler | 7d13564 | 2021-02-04 12:44:17 -0600 | [diff] [blame] | 172 |     /** | 
 | 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 Spinler | 623635c | 2021-03-29 13:13:59 -0500 | [diff] [blame] | 179 |     /** | 
 | 180 |      * @brief Timer callback function that deals with sensors using | 
 | 181 |      *        the 'count' method for determining functional status. | 
| Matt Spinler | fdfcc67 | 2021-06-01 14:51:06 -0600 | [diff] [blame] | 182 |      * | 
 | 183 |      * @param[in] sensor - TachSensor object | 
| Matt Spinler | 623635c | 2021-03-29 13:13:59 -0500 | [diff] [blame] | 184 |      */ | 
| Matt Spinler | fdfcc67 | 2021-06-01 14:51:06 -0600 | [diff] [blame] | 185 |     void countTimerExpired(TachSensor& sensor); | 
| Matt Spinler | 623635c | 2021-03-29 13:13:59 -0500 | [diff] [blame] | 186 |  | 
| Matthew Barth | 177fe98 | 2020-05-26 11:05:19 -0500 | [diff] [blame] | 187 |   private: | 
 | 188 |     /** | 
 | 189 |      * @brief Returns true if the sensor input is not within | 
 | 190 |      * some deviation of the target. | 
 | 191 |      * | 
 | 192 |      * @param[in] sensor - the sensor to check | 
 | 193 |      */ | 
 | 194 |     bool outOfRange(const TachSensor& sensor); | 
| Matthew Barth | f552ea5 | 2018-01-15 16:22:04 -0600 | [diff] [blame] | 195 |  | 
| Matthew Barth | 177fe98 | 2020-05-26 11:05:19 -0500 | [diff] [blame] | 196 |     /** | 
| Matthew Barth | 7c23a04 | 2021-01-26 16:21:45 -0600 | [diff] [blame] | 197 |      * @brief Returns the number sensors that are nonfunctional | 
| Matthew Barth | 177fe98 | 2020-05-26 11:05:19 -0500 | [diff] [blame] | 198 |      */ | 
| Matthew Barth | 7c23a04 | 2021-01-26 16:21:45 -0600 | [diff] [blame] | 199 |     size_t countNonFunctionalSensors(); | 
| Matt Spinler | abf8da3 | 2017-04-27 14:08:45 -0500 | [diff] [blame] | 200 |  | 
| Matthew Barth | 177fe98 | 2020-05-26 11:05:19 -0500 | [diff] [blame] | 201 |     /** | 
 | 202 |      * @brief Updates the Functional property in the inventory | 
 | 203 |      *        for the fan based on the value passed in. | 
 | 204 |      * | 
 | 205 |      * @param[in] functional - If the Functional property should | 
 | 206 |      *                         be set to true or false. | 
 | 207 |      */ | 
 | 208 |     void updateInventory(bool functional); | 
| Matt Spinler | abf8da3 | 2017-04-27 14:08:45 -0500 | [diff] [blame] | 209 |  | 
| Matthew Barth | 177fe98 | 2020-05-26 11:05:19 -0500 | [diff] [blame] | 210 |     /** | 
| Matt Spinler | b0412d0 | 2020-10-12 16:53:52 -0500 | [diff] [blame] | 211 |      * @brief Called by _monitorTimer to start fan monitoring some | 
 | 212 |      *        amount of time after startup. | 
 | 213 |      */ | 
 | 214 |     void startMonitor(); | 
 | 215 |  | 
 | 216 |     /** | 
| Matt Spinler | b63aa09 | 2020-10-14 09:45:11 -0500 | [diff] [blame] | 217 |      * @brief Called when the fan presence property changes on D-Bus | 
 | 218 |      * | 
 | 219 |      * @param[in] msg - The message from the propertiesChanged signal | 
 | 220 |      */ | 
 | 221 |     void presenceChanged(sdbusplus::message::message& msg); | 
 | 222 |  | 
 | 223 |     /** | 
| Matt Spinler | 7d13564 | 2021-02-04 12:44:17 -0600 | [diff] [blame] | 224 |      * @brief Called when there is an interfacesAdded signal on the | 
 | 225 |      *        fan D-Bus path so the code can look for the 'Present' | 
 | 226 |      *        property value. | 
 | 227 |      * | 
 | 228 |      * @param[in] msg - The message from the interfacesAdded signal | 
 | 229 |      */ | 
 | 230 |     void presenceIfaceAdded(sdbusplus::message::message& msg); | 
 | 231 |  | 
 | 232 |     /** | 
| Matthew Barth | 177fe98 | 2020-05-26 11:05:19 -0500 | [diff] [blame] | 233 |      * @brief the dbus object | 
 | 234 |      */ | 
 | 235 |     sdbusplus::bus::bus& _bus; | 
| Matt Spinler | abf8da3 | 2017-04-27 14:08:45 -0500 | [diff] [blame] | 236 |  | 
| Matthew Barth | 177fe98 | 2020-05-26 11:05:19 -0500 | [diff] [blame] | 237 |     /** | 
 | 238 |      * @brief The inventory name of the fan | 
 | 239 |      */ | 
 | 240 |     const std::string _name; | 
| Matt Spinler | b1e1851 | 2017-04-27 14:42:33 -0500 | [diff] [blame] | 241 |  | 
| Matthew Barth | 177fe98 | 2020-05-26 11:05:19 -0500 | [diff] [blame] | 242 |     /** | 
 | 243 |      * @brief The percentage that the input speed must be below | 
 | 244 |      *        the target speed to be considered an error. | 
 | 245 |      *        Between 0 and 100. | 
 | 246 |      */ | 
 | 247 |     const size_t _deviation; | 
| Matt Spinler | abf8da3 | 2017-04-27 14:08:45 -0500 | [diff] [blame] | 248 |  | 
| Matthew Barth | 177fe98 | 2020-05-26 11:05:19 -0500 | [diff] [blame] | 249 |     /** | 
 | 250 |      * The number of sensors that must be nonfunctional at the | 
 | 251 |      * same time in order for the fan to be set to nonfunctional | 
 | 252 |      * in the inventory. | 
 | 253 |      */ | 
 | 254 |     const size_t _numSensorFailsForNonFunc; | 
| Matt Spinler | abf8da3 | 2017-04-27 14:08:45 -0500 | [diff] [blame] | 255 |  | 
| Matthew Barth | 177fe98 | 2020-05-26 11:05:19 -0500 | [diff] [blame] | 256 |     /** | 
| Jolie Ku | 5d564a9 | 2020-10-23 09:04:28 +0800 | [diff] [blame] | 257 |      * The number of failed sensors | 
 | 258 |      */ | 
 | 259 |     size_t _numFailedSensor = 0; | 
 | 260 |  | 
 | 261 |     /** | 
| Matthew Barth | 177fe98 | 2020-05-26 11:05:19 -0500 | [diff] [blame] | 262 |      * @brief The current functional state of the fan | 
 | 263 |      */ | 
 | 264 |     bool _functional = true; | 
| Matt Spinler | abf8da3 | 2017-04-27 14:08:45 -0500 | [diff] [blame] | 265 |  | 
| Matthew Barth | 177fe98 | 2020-05-26 11:05:19 -0500 | [diff] [blame] | 266 |     /** | 
 | 267 |      * The sensor objects for the fan | 
 | 268 |      */ | 
 | 269 |     std::vector<std::shared_ptr<TachSensor>> _sensors; | 
| Matt Spinler | abf8da3 | 2017-04-27 14:08:45 -0500 | [diff] [blame] | 270 |  | 
| Matthew Barth | 177fe98 | 2020-05-26 11:05:19 -0500 | [diff] [blame] | 271 |     /** | 
 | 272 |      * The tach trust manager object | 
 | 273 |      */ | 
 | 274 |     std::unique_ptr<trust::Manager>& _trustManager; | 
| Matt Spinler | b0412d0 | 2020-10-12 16:53:52 -0500 | [diff] [blame] | 275 |  | 
 | 276 | #ifdef MONITOR_USE_JSON | 
 | 277 |     /** | 
 | 278 |      * @brief The number of seconds to wait after startup until | 
 | 279 |      *        fan sensors should checked against their targets. | 
 | 280 |      */ | 
 | 281 |     size_t _monitorDelay; | 
 | 282 |  | 
 | 283 |     /** | 
 | 284 |      * @brief Expires after _monitorDelay to start fan monitoring. | 
 | 285 |      */ | 
 | 286 |     sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> _monitorTimer; | 
 | 287 | #endif | 
 | 288 |  | 
 | 289 |     /** | 
 | 290 |      * @brief Set to true when monitoring can start. | 
 | 291 |      */ | 
 | 292 |     bool _monitorReady = false; | 
 | 293 |  | 
 | 294 |     /** | 
 | 295 |      * @brief Reference to the System object | 
 | 296 |      */ | 
 | 297 |     System& _system; | 
| Matt Spinler | b63aa09 | 2020-10-14 09:45:11 -0500 | [diff] [blame] | 298 |  | 
 | 299 |     /** | 
 | 300 |      * @brief The match object for propertiesChanged signals | 
 | 301 |      *        for the inventory item interface to track the | 
 | 302 |      *        Present property. | 
 | 303 |      */ | 
 | 304 |     sdbusplus::bus::match::match _presenceMatch; | 
 | 305 |  | 
 | 306 |     /** | 
| Matt Spinler | 7d13564 | 2021-02-04 12:44:17 -0600 | [diff] [blame] | 307 |      * @brief The match object for the interfacesAdded signal | 
 | 308 |      *        for the interface that has the Present property. | 
 | 309 |      */ | 
 | 310 |     sdbusplus::bus::match::match _presenceIfaceAddedMatch; | 
 | 311 |  | 
 | 312 |     /** | 
| Matt Spinler | b63aa09 | 2020-10-14 09:45:11 -0500 | [diff] [blame] | 313 |      * @brief The current presence state | 
 | 314 |      */ | 
 | 315 |     bool _present = false; | 
| Matt Spinler | 27f6b68 | 2020-10-27 08:43:37 -0500 | [diff] [blame] | 316 |  | 
 | 317 |     /** | 
 | 318 |      * @brief The number of seconds to wait after a fan is removed before | 
 | 319 |      *        creating an event log for it.  If std::nullopt, then no | 
 | 320 |      *        event log will be created. | 
 | 321 |      */ | 
 | 322 |     const std::optional<size_t> _fanMissingErrorDelay; | 
 | 323 |  | 
 | 324 |     /** | 
 | 325 |      * @brief The timer that uses the _fanMissingErrorDelay timeout, | 
 | 326 |      *        at the end of which an event log will be created. | 
 | 327 |      */ | 
 | 328 |     std::unique_ptr< | 
 | 329 |         sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>> | 
 | 330 |         _fanMissingErrorTimer; | 
| Matt Spinler | 623635c | 2021-03-29 13:13:59 -0500 | [diff] [blame] | 331 |  | 
 | 332 |     /** | 
| Matt Spinler | a3584bd | 2021-03-29 15:48:30 -0500 | [diff] [blame] | 333 |      * @brief If the fan and sensors should be set to functional when | 
 | 334 |      *        a fan plug is detected. | 
 | 335 |      */ | 
 | 336 |     bool _setFuncOnPresent; | 
| Matt Spinler | abf8da3 | 2017-04-27 14:08:45 -0500 | [diff] [blame] | 337 | }; | 
 | 338 |  | 
| Matthew Barth | 177fe98 | 2020-05-26 11:05:19 -0500 | [diff] [blame] | 339 | } // namespace monitor | 
 | 340 | } // namespace fan | 
 | 341 | } // namespace phosphor |