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