1abf8da36SMatt Spinler #pragma once 2abf8da36SMatt Spinler 3b0412d07SMatt Spinler #include "config.h" 4b0412d07SMatt Spinler 5abf8da36SMatt Spinler #include "tach_sensor.hpp" 6c39e859bSMatt Spinler #include "trust_manager.hpp" 7abf8da36SMatt Spinler #include "types.hpp" 8abf8da36SMatt Spinler 9177fe986SMatthew Barth #include <sdbusplus/bus.hpp> 10177fe986SMatthew Barth #include <sdeventplus/event.hpp> 11177fe986SMatthew Barth 12177fe986SMatthew Barth #include <tuple> 13177fe986SMatthew Barth #include <vector> 14177fe986SMatthew Barth 15abf8da36SMatt Spinler namespace phosphor 16abf8da36SMatt Spinler { 17abf8da36SMatt Spinler namespace fan 18abf8da36SMatt Spinler { 19abf8da36SMatt Spinler namespace monitor 20abf8da36SMatt Spinler { 21abf8da36SMatt Spinler 22b0412d07SMatt Spinler class System; 23b0412d07SMatt Spinler 24edaeb31cSBrad Bishop /** 25abf8da36SMatt Spinler * @class Fan 26abf8da36SMatt Spinler * 27abf8da36SMatt Spinler * Represents a fan, which can contain 1 or more sensors which 28abf8da36SMatt Spinler * loosely correspond to rotors. See below. 29abf8da36SMatt Spinler * 30abf8da36SMatt Spinler * There is a sensor when hwmon exposes one, which means there is a 31abf8da36SMatt Spinler * speed value to be read. Sometimes there is a sensor per rotor, 32abf8da36SMatt Spinler * and other times multiple rotors just use 1 sensor total where 33abf8da36SMatt Spinler * the sensor reports the slowest speed of all of the rotors. 34abf8da36SMatt Spinler * 35abf8da36SMatt Spinler * A rotor's speed is set by writing the Target value of a sensor. 36abf8da36SMatt Spinler * Sometimes each sensor in a fan supports having a Target, and other 37abf8da36SMatt Spinler * times not all of them do. A TachSensor object knows if it supports 38abf8da36SMatt Spinler * the Target property. 39abf8da36SMatt Spinler * 40abf8da36SMatt Spinler * The strategy for monitoring fan speeds is as follows: 41abf8da36SMatt Spinler * 42abf8da36SMatt Spinler * Every time a Target (new speed written) or Input (actual speed read) 43abf8da36SMatt Spinler * sensor changes, check if the input value is within some range of the target 44abf8da36SMatt Spinler * value. If it isn't, start a timer at the end of which the sensor will be 45abf8da36SMatt Spinler * set to not functional. If enough sensors in the fan are now nonfunctional, 46abf8da36SMatt Spinler * set the whole fan to nonfunctional in the inventory. 47abf8da36SMatt Spinler * 48abf8da36SMatt Spinler * When sensor inputs come back within a specified range of the target, 49abf8da36SMatt Spinler * stop its timer if running, make the sensor functional again if it wasn't, 50abf8da36SMatt Spinler * and if enough sensors in the fan are now functional set the whole fan 51abf8da36SMatt Spinler * back to functional in the inventory. 52abf8da36SMatt Spinler */ 53abf8da36SMatt Spinler class Fan 54abf8da36SMatt Spinler { 55b1e18514SMatt Spinler using Property = std::string; 56c21d0b36SPatrick Williams using Value = std::variant<bool>; 57b1e18514SMatt Spinler using PropertyMap = std::map<Property, Value>; 58b1e18514SMatt Spinler 59b1e18514SMatt Spinler using Interface = std::string; 60b1e18514SMatt Spinler using InterfaceMap = std::map<Interface, PropertyMap>; 61b1e18514SMatt Spinler 62b1e18514SMatt Spinler using Object = sdbusplus::message::object_path; 63b1e18514SMatt Spinler using ObjectMap = std::map<Object, InterfaceMap>; 64abf8da36SMatt Spinler 65abf8da36SMatt Spinler public: 66abf8da36SMatt Spinler Fan() = delete; 67abf8da36SMatt Spinler Fan(const Fan&) = delete; 68abf8da36SMatt Spinler Fan(Fan&&) = default; 69abf8da36SMatt Spinler Fan& operator=(const Fan&) = delete; 70abf8da36SMatt Spinler Fan& operator=(Fan&&) = default; 71abf8da36SMatt Spinler ~Fan() = default; 72abf8da36SMatt Spinler 73abf8da36SMatt Spinler /** 74abf8da36SMatt Spinler * @brief Constructor 75abf8da36SMatt Spinler * 766ad28430SMatthew Barth * @param mode - mode of fan monitor 77abf8da36SMatt Spinler * @param bus - the dbus object 781cfc2f11SWilliam A. Kennington III * @param event - event loop reference 79c39e859bSMatt Spinler * @param trust - the tach trust manager 80abf8da36SMatt Spinler * @param def - the fan definition structure 81b0412d07SMatt Spinler * @param system - Reference to the system object 82abf8da36SMatt Spinler */ 83cb356d48SPatrick Williams Fan(Mode mode, sdbusplus::bus_t& bus, const sdeventplus::Event& event, 84b0412d07SMatt Spinler std::unique_ptr<trust::Manager>& trust, const FanDefinition& def, 85b0412d07SMatt Spinler System& system); 86abf8da36SMatt Spinler 87ebaae611SMatt Spinler /** 88ebaae611SMatt Spinler * @brief Callback function for when an input sensor changes 89ebaae611SMatt Spinler * 90ebaae611SMatt Spinler * Starts a timer, where if it expires then the sensor 91a9406a77SMatt Spinler * was out of range for too long and can be considered not functional. 92ebaae611SMatt Spinler */ 93ebaae611SMatt Spinler void tachChanged(TachSensor& sensor); 94ebaae611SMatt Spinler 95ebaae611SMatt Spinler /** 96ebaae611SMatt Spinler * @brief Calls tachChanged(sensor) on each sensor 97ebaae611SMatt Spinler */ 98ebaae611SMatt Spinler void tachChanged(); 99abf8da36SMatt Spinler 100a9406a77SMatt Spinler /** 10169f2f48eSJolie Ku * @brief The callback function for the method 102a9406a77SMatt Spinler * 103a9406a77SMatt Spinler * Sets the sensor to not functional. 104a9406a77SMatt Spinler * If enough sensors are now not functional, 105a9406a77SMatt Spinler * updates the functional status of the whole 106a9406a77SMatt Spinler * fan in the inventory. 107a9406a77SMatt Spinler * 10869f2f48eSJolie Ku * @param[in] sensor - the sensor for state update 109a9406a77SMatt Spinler */ 11069f2f48eSJolie Ku void updateState(TachSensor& sensor); 111a9406a77SMatt Spinler 1124d982856SMatthew Barth /** 1134d982856SMatthew Barth * @brief Get the name of the fan 1144d982856SMatthew Barth * 1154d982856SMatthew Barth * @return - The fan name 1164d982856SMatthew Barth */ getName() const1174d982856SMatthew Barth inline const std::string& getName() const 1184d982856SMatthew Barth { 1194d982856SMatthew Barth return _name; 1204d982856SMatthew Barth } 1214d982856SMatthew Barth 122f552ea5cSMatthew Barth /** 123f552ea5cSMatthew Barth * @brief Finds the target speed of this fan 124f552ea5cSMatthew Barth * 125f552ea5cSMatthew Barth * Finds the target speed from the list of sensors that make up this 126f552ea5cSMatthew Barth * fan. At least one sensor should contain a target speed value. 127f552ea5cSMatthew Barth * 128f552ea5cSMatthew Barth * @return - The target speed found from the list of sensors on the fan 129f552ea5cSMatthew Barth */ 130f552ea5cSMatthew Barth uint64_t findTargetSpeed(); 131f552ea5cSMatthew Barth 132b63aa09eSMatt Spinler /** 133b63aa09eSMatt Spinler * @brief Returns the contained TachSensor objects 134b63aa09eSMatt Spinler * 135b63aa09eSMatt Spinler * @return std::vector<std::shared_ptr<TachSensor>> - The sensors 136b63aa09eSMatt Spinler */ sensors() const137b63aa09eSMatt Spinler const std::vector<std::shared_ptr<TachSensor>>& sensors() const 138b63aa09eSMatt Spinler { 139b63aa09eSMatt Spinler return _sensors; 140b63aa09eSMatt Spinler } 141b63aa09eSMatt Spinler 142b63aa09eSMatt Spinler /** 143b63aa09eSMatt Spinler * @brief Returns the presence status of the fan 144b63aa09eSMatt Spinler * 145b63aa09eSMatt Spinler * @return bool - If the fan is present or not 146b63aa09eSMatt Spinler */ present() const147b63aa09eSMatt Spinler bool present() const 148b63aa09eSMatt Spinler { 149b63aa09eSMatt Spinler return _present; 150b63aa09eSMatt Spinler } 151b63aa09eSMatt Spinler 152f13b42e2SMatt Spinler /** 153f13b42e2SMatt Spinler * @brief Called from TachSensor when its error timer expires 154f13b42e2SMatt Spinler * so an event log calling out the fan can be created. 155f13b42e2SMatt Spinler * 156f13b42e2SMatt Spinler * @param[in] sensor - The nonfunctional sensor 157f13b42e2SMatt Spinler */ 158f13b42e2SMatt Spinler void sensorErrorTimerExpired(const TachSensor& sensor); 159f13b42e2SMatt Spinler 160fcb0dbcbSMatthew Barth /** 161fcb0dbcbSMatthew Barth * @brief Process the state of the given tach sensor without checking 162fcb0dbcbSMatthew Barth * any trust groups the sensor may be included in 163fcb0dbcbSMatthew Barth * 164fcb0dbcbSMatthew Barth * @param[in] sensor - Tach sensor to process 165fcb0dbcbSMatthew Barth * 166fcb0dbcbSMatthew Barth * This function is intended to check the current state of a tach sensor 167fcb0dbcbSMatthew Barth * regardless of whether or not the tach sensor is configured to be in any 168fcb0dbcbSMatthew Barth * trust groups. 169fcb0dbcbSMatthew Barth */ 170fcb0dbcbSMatthew Barth void process(TachSensor& sensor); 171fcb0dbcbSMatthew Barth 1727d135641SMatt Spinler /** 1737d135641SMatt Spinler * @brief The function that runs when the power state changes 1747d135641SMatt Spinler * 1757d135641SMatt Spinler * @param[in] powerStateOn - If power is now on or not 1767d135641SMatt Spinler */ 1777d135641SMatt Spinler void powerStateChanged(bool powerStateOn); 1787d135641SMatt Spinler 179623635c6SMatt Spinler /** 180623635c6SMatt Spinler * @brief Timer callback function that deals with sensors using 181623635c6SMatt Spinler * the 'count' method for determining functional status. 182fdfcc679SMatt Spinler * 183fdfcc679SMatt Spinler * @param[in] sensor - TachSensor object 184623635c6SMatt Spinler */ 185fdfcc679SMatt Spinler void countTimerExpired(TachSensor& sensor); 186623635c6SMatt Spinler 187bb449c1cSMatt Spinler /** 188bb449c1cSMatt Spinler * @brief Returns the number of tach sensors (Sensor.Value ifaces) 189bb449c1cSMatt Spinler * on D-Bus at the last power on. 190bb449c1cSMatt Spinler */ numSensorsOnDBusAtPowerOn() const191bb449c1cSMatt Spinler inline size_t numSensorsOnDBusAtPowerOn() const 192bb449c1cSMatt Spinler { 193bb449c1cSMatt Spinler return _numSensorsOnDBusAtPowerOn; 194bb449c1cSMatt Spinler } 195bb449c1cSMatt Spinler 196abf8da36SMatt Spinler /** 197abf8da36SMatt Spinler * @brief Returns true if the sensor input is not within 198abf8da36SMatt Spinler * some deviation of the target. 199abf8da36SMatt Spinler * 200abf8da36SMatt Spinler * @param[in] sensor - the sensor to check 201abf8da36SMatt Spinler */ 202abf8da36SMatt Spinler bool outOfRange(const TachSensor& sensor); 203abf8da36SMatt Spinler 204d16d464aSMatt Spinler private: 205abf8da36SMatt Spinler /** 2067c23a049SMatthew Barth * @brief Returns the number sensors that are nonfunctional 207abf8da36SMatt Spinler */ 208ce6820abSMike Capps size_t countNonFunctionalSensors() const; 209abf8da36SMatt Spinler 210b1e18514SMatt Spinler /** 211b1e18514SMatt Spinler * @brief Updates the Functional property in the inventory 212b1e18514SMatt Spinler * for the fan based on the value passed in. 213b1e18514SMatt Spinler * 214b1e18514SMatt Spinler * @param[in] functional - If the Functional property should 215b1e18514SMatt Spinler * be set to true or false. 2169ff48777SMike Capps * 2179ff48777SMike Capps * @return - True if an exception was encountered during update 218b1e18514SMatt Spinler */ 2199ff48777SMike Capps bool updateInventory(bool functional); 220b1e18514SMatt Spinler 221b1e18514SMatt Spinler /** 222b0412d07SMatt Spinler * @brief Called by _monitorTimer to start fan monitoring some 223b0412d07SMatt Spinler * amount of time after startup. 224b0412d07SMatt Spinler */ 225b0412d07SMatt Spinler void startMonitor(); 226b0412d07SMatt Spinler 227b0412d07SMatt Spinler /** 228b63aa09eSMatt Spinler * @brief Called when the fan presence property changes on D-Bus 229b63aa09eSMatt Spinler * 230b63aa09eSMatt Spinler * @param[in] msg - The message from the propertiesChanged signal 231b63aa09eSMatt Spinler */ 232cb356d48SPatrick Williams void presenceChanged(sdbusplus::message_t& msg); 233b63aa09eSMatt Spinler 234b63aa09eSMatt Spinler /** 2357d135641SMatt Spinler * @brief Called when there is an interfacesAdded signal on the 2367d135641SMatt Spinler * fan D-Bus path so the code can look for the 'Present' 2377d135641SMatt Spinler * property value. 2387d135641SMatt Spinler * 2397d135641SMatt Spinler * @param[in] msg - The message from the interfacesAdded signal 2407d135641SMatt Spinler */ 241cb356d48SPatrick Williams void presenceIfaceAdded(sdbusplus::message_t& msg); 2427d135641SMatt Spinler 2437d135641SMatt Spinler /** 244abf8da36SMatt Spinler * @brief the dbus object 245abf8da36SMatt Spinler */ 246cb356d48SPatrick Williams sdbusplus::bus_t& _bus; 247abf8da36SMatt Spinler 248abf8da36SMatt Spinler /** 249abf8da36SMatt Spinler * @brief The inventory name of the fan 250abf8da36SMatt Spinler */ 251abf8da36SMatt Spinler const std::string _name; 252abf8da36SMatt Spinler 253abf8da36SMatt Spinler /** 254abf8da36SMatt Spinler * @brief The percentage that the input speed must be below 255abf8da36SMatt Spinler * the target speed to be considered an error. 256abf8da36SMatt Spinler * Between 0 and 100. 257abf8da36SMatt Spinler */ 258abf8da36SMatt Spinler const size_t _deviation; 259abf8da36SMatt Spinler 260abf8da36SMatt Spinler /** 261*f724c16bSMatt Spinler * @brief The percentage that the input speed must be above 262*f724c16bSMatt Spinler * the target speed to be considered an error. 263*f724c16bSMatt Spinler * Between 0 and 100. 264*f724c16bSMatt Spinler */ 265*f724c16bSMatt Spinler const size_t _upperDeviation; 266*f724c16bSMatt Spinler 267*f724c16bSMatt Spinler /** 268abf8da36SMatt Spinler * The number of sensors that must be nonfunctional at the 269abf8da36SMatt Spinler * same time in order for the fan to be set to nonfunctional 270abf8da36SMatt Spinler * in the inventory. 271abf8da36SMatt Spinler */ 272abf8da36SMatt Spinler const size_t _numSensorFailsForNonFunc; 273abf8da36SMatt Spinler 274abf8da36SMatt Spinler /** 2755d564a9fSJolie Ku * The number of failed sensors 2765d564a9fSJolie Ku */ 2775d564a9fSJolie Ku size_t _numFailedSensor = 0; 2785d564a9fSJolie Ku 2795d564a9fSJolie Ku /** 280abf8da36SMatt Spinler * @brief The current functional state of the fan 281abf8da36SMatt Spinler */ 282abf8da36SMatt Spinler bool _functional = true; 283abf8da36SMatt Spinler 284abf8da36SMatt Spinler /** 285abf8da36SMatt Spinler * The sensor objects for the fan 286abf8da36SMatt Spinler */ 28732affb98SMatthew Barth std::vector<std::shared_ptr<TachSensor>> _sensors; 288c39e859bSMatt Spinler 289c39e859bSMatt Spinler /** 290c39e859bSMatt Spinler * The tach trust manager object 291c39e859bSMatt Spinler */ 292c39e859bSMatt Spinler std::unique_ptr<trust::Manager>& _trustManager; 293b0412d07SMatt Spinler 294b0412d07SMatt Spinler #ifdef MONITOR_USE_JSON 295b0412d07SMatt Spinler /** 296b0412d07SMatt Spinler * @brief The number of seconds to wait after startup until 297b0412d07SMatt Spinler * fan sensors should checked against their targets. 298b0412d07SMatt Spinler */ 299b0412d07SMatt Spinler size_t _monitorDelay; 300b0412d07SMatt Spinler 301b0412d07SMatt Spinler /** 302b0412d07SMatt Spinler * @brief Expires after _monitorDelay to start fan monitoring. 303b0412d07SMatt Spinler */ 304b0412d07SMatt Spinler sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> _monitorTimer; 305b0412d07SMatt Spinler #endif 306b0412d07SMatt Spinler 307b0412d07SMatt Spinler /** 308b0412d07SMatt Spinler * @brief Set to true when monitoring can start. 309b0412d07SMatt Spinler */ 310b0412d07SMatt Spinler bool _monitorReady = false; 311b0412d07SMatt Spinler 312b0412d07SMatt Spinler /** 313b0412d07SMatt Spinler * @brief Reference to the System object 314b0412d07SMatt Spinler */ 315b0412d07SMatt Spinler System& _system; 316b63aa09eSMatt Spinler 317b63aa09eSMatt Spinler /** 318b63aa09eSMatt Spinler * @brief The match object for propertiesChanged signals 319b63aa09eSMatt Spinler * for the inventory item interface to track the 320b63aa09eSMatt Spinler * Present property. 321b63aa09eSMatt Spinler */ 322cb356d48SPatrick Williams sdbusplus::bus::match_t _presenceMatch; 323b63aa09eSMatt Spinler 324b63aa09eSMatt Spinler /** 3257d135641SMatt Spinler * @brief The match object for the interfacesAdded signal 3267d135641SMatt Spinler * for the interface that has the Present property. 3277d135641SMatt Spinler */ 328cb356d48SPatrick Williams sdbusplus::bus::match_t _presenceIfaceAddedMatch; 3297d135641SMatt Spinler 3307d135641SMatt Spinler /** 331b63aa09eSMatt Spinler * @brief The current presence state 332b63aa09eSMatt Spinler */ 333b63aa09eSMatt Spinler bool _present = false; 33427f6b686SMatt Spinler 33527f6b686SMatt Spinler /** 33627f6b686SMatt Spinler * @brief The number of seconds to wait after a fan is removed before 33727f6b686SMatt Spinler * creating an event log for it. If std::nullopt, then no 33827f6b686SMatt Spinler * event log will be created. 33927f6b686SMatt Spinler */ 34027f6b686SMatt Spinler const std::optional<size_t> _fanMissingErrorDelay; 34127f6b686SMatt Spinler 34227f6b686SMatt Spinler /** 34327f6b686SMatt Spinler * @brief The timer that uses the _fanMissingErrorDelay timeout, 34427f6b686SMatt Spinler * at the end of which an event log will be created. 34527f6b686SMatt Spinler */ 34627f6b686SMatt Spinler std::unique_ptr< 34727f6b686SMatt Spinler sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>> 34827f6b686SMatt Spinler _fanMissingErrorTimer; 349623635c6SMatt Spinler 350623635c6SMatt Spinler /** 351a3584bd2SMatt Spinler * @brief If the fan and sensors should be set to functional when 352a3584bd2SMatt Spinler * a fan plug is detected. 353a3584bd2SMatt Spinler */ 354a3584bd2SMatt Spinler bool _setFuncOnPresent; 355bb449c1cSMatt Spinler 356bb449c1cSMatt Spinler /** 357bb449c1cSMatt Spinler * @brief The number of sensors that have their Sensor.Value interfaces 358bb449c1cSMatt Spinler * on D-Bus at the last power on. 359bb449c1cSMatt Spinler * 360bb449c1cSMatt Spinler * Will be zero until the power turns on the first time. 361bb449c1cSMatt Spinler */ 362bb449c1cSMatt Spinler size_t _numSensorsOnDBusAtPowerOn = 0; 363abf8da36SMatt Spinler }; 364abf8da36SMatt Spinler 365177fe986SMatthew Barth } // namespace monitor 366177fe986SMatthew Barth } // namespace fan 367177fe986SMatthew Barth } // namespace phosphor 368