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