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