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