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