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