1 #pragma once 2 3 #include <sdbusplus/bus.hpp> 4 #include <sdbusplus/server.hpp> 5 #include <sdeventplus/clock.hpp> 6 #include <sdeventplus/event.hpp> 7 #include <sdeventplus/utility/timer.hpp> 8 9 #include <chrono> 10 11 namespace phosphor 12 { 13 namespace fan 14 { 15 namespace monitor 16 { 17 18 class Fan; 19 20 constexpr auto FAN_SENSOR_PATH = "/xyz/openbmc_project/sensors/fan_tach/"; 21 22 /** 23 * The mode fan monitor will run in: 24 * - init - only do the initialization steps 25 * - monitor - run normal monitoring algorithm 26 */ 27 enum class Mode 28 { 29 init, 30 monitor 31 }; 32 33 /** 34 * The mode that the timer is running in: 35 * - func - Transition to functional state timer 36 * - nonfunc - Transition to nonfunctional state timer 37 */ 38 enum class TimerMode 39 { 40 func, 41 nonfunc 42 }; 43 44 /** 45 * @class TachSensor 46 * 47 * This class represents the sensor that reads a tach value. 48 * It may also support a Target, which is the property used to 49 * set a speed. Since it doesn't necessarily have a Target, it 50 * won't for sure know if it is running too slow, so it leaves 51 * that determination to other code. 52 * 53 * This class has a parent Fan object that knows about all 54 * sensors for that fan. 55 */ 56 class TachSensor 57 { 58 public: 59 TachSensor() = delete; 60 TachSensor(const TachSensor&) = delete; 61 // TachSensor is not moveable since the this pointer is used as systemd 62 // callback context. 63 TachSensor(TachSensor&&) = delete; 64 TachSensor& operator=(const TachSensor&) = delete; 65 TachSensor& operator=(TachSensor&&) = delete; 66 ~TachSensor() = default; 67 68 /** 69 * @brief Constructor 70 * 71 * @param[in] mode - mode of fan monitor 72 * @param[in] bus - the dbus object 73 * @param[in] fan - the parent fan object 74 * @param[in] id - the id of the sensor 75 * @param[in] hasTarget - if the sensor supports 76 * setting the speed 77 * @param[in] funcDelay - Delay to mark functional 78 * @param[in] interface - the interface of the target 79 * @param[in] factor - the factor of the sensor target 80 * @param[in] offset - the offset of the sensor target 81 * @param[in] timeout - Normal timeout value to use 82 * @param[in] errorDelay - Delay in seconds before creating an error 83 * or std::nullopt if no errors. 84 * 85 * @param[in] event - Event loop reference 86 */ 87 TachSensor(Mode mode, sdbusplus::bus::bus& bus, Fan& fan, 88 const std::string& id, bool hasTarget, size_t funcDelay, 89 const std::string& interface, double factor, int64_t offset, 90 size_t timeout, const std::optional<size_t>& errorDelay, 91 const sdeventplus::Event& event); 92 93 /** 94 * @brief Returns the target speed value 95 */ 96 uint64_t getTarget() const; 97 98 /** 99 * @brief Returns the input speed value 100 */ 101 inline double getInput() const 102 { 103 return _tachInput; 104 } 105 106 /** 107 * @brief Returns true if sensor has a target 108 */ 109 inline bool hasTarget() const 110 { 111 return _hasTarget; 112 } 113 114 /** 115 * @brief Returns the interface of the sensor target 116 */ 117 inline std::string getInterface() const 118 { 119 return _interface; 120 } 121 122 /** 123 * @brief Returns the factor of the sensor target 124 */ 125 inline double getFactor() const 126 { 127 return _factor; 128 } 129 130 /** 131 * @brief Returns the offset of the sensor target 132 */ 133 inline int64_t getOffset() const 134 { 135 return _offset; 136 } 137 138 /** 139 * Returns true if the hardware behind this 140 * sensor is considered working OK/functional. 141 */ 142 inline bool functional() const 143 { 144 return _functional; 145 } 146 147 /** 148 * Set the functional status and update inventory to match 149 */ 150 void setFunctional(bool functional); 151 152 /** 153 * @brief Says if the timer is running or not 154 * 155 * @return bool - if timer is currently running 156 */ 157 inline bool timerRunning() 158 { 159 return _timer.isEnabled(); 160 } 161 162 /** 163 * @brief Stops the timer when the given mode differs and starts 164 * the associated timer for the mode given if not already running 165 * 166 * @param[in] mode - mode of timer to start 167 */ 168 void startTimer(TimerMode mode); 169 170 /** 171 * @brief Stops the timer 172 */ 173 inline void stopTimer() 174 { 175 _timer.setEnabled(false); 176 } 177 178 /** 179 * @brief Return the given timer mode's delay time 180 * 181 * @param[in] mode - mode of timer to get delay time for 182 */ 183 std::chrono::microseconds getDelay(TimerMode mode); 184 185 /** 186 * Returns the sensor name 187 */ 188 inline const std::string& name() const 189 { 190 return _name; 191 }; 192 193 /** 194 * @brief Says if the error timer is running 195 * 196 * @return bool - If the timer is running 197 */ 198 bool errorTimerRunning() const 199 { 200 if (_errorTimer && _errorTimer->isEnabled()) 201 { 202 return true; 203 } 204 return false; 205 } 206 207 private: 208 /** 209 * @brief Returns the match string to use for matching 210 * on a properties changed signal. 211 */ 212 std::string getMatchString(const std::string& interface); 213 214 /** 215 * @brief Reads the Target property and stores in _tachTarget. 216 * Also calls Fan::tachChanged(). 217 * 218 * @param[in] msg - the dbus message 219 */ 220 void handleTargetChange(sdbusplus::message::message& msg); 221 222 /** 223 * @brief Reads the Value property and stores in _tachInput. 224 * Also calls Fan::tachChanged(). 225 * 226 * @param[in] msg - the dbus message 227 */ 228 void handleTachChange(sdbusplus::message::message& msg); 229 230 /** 231 * @brief Updates the Functional property in the inventory 232 * for this tach sensor based on the value passed in. 233 * 234 * @param[in] functional - If the Functional property should 235 * be set to true or false. 236 */ 237 void updateInventory(bool functional); 238 239 /** 240 * @brief the dbus object 241 */ 242 sdbusplus::bus::bus& _bus; 243 244 /** 245 * @brief Reference to the parent Fan object 246 */ 247 Fan& _fan; 248 249 /** 250 * @brief The name of the sensor, including the full path 251 * 252 * For example /xyz/openbmc_project/sensors/fan_tach/fan0 253 */ 254 const std::string _name; 255 256 /** 257 * @brief The inventory name of the sensor, including the full path 258 */ 259 const std::string _invName; 260 261 /** 262 * @brief If functional (not too slow). The parent 263 * fan object sets this. 264 */ 265 bool _functional; 266 267 /** 268 * @brief If the sensor has a Target property (can set speed) 269 */ 270 const bool _hasTarget; 271 272 /** 273 * @brief Amount of time to delay updating to functional 274 */ 275 const size_t _funcDelay; 276 277 /** 278 * @brief The interface that the target implements 279 */ 280 const std::string _interface; 281 282 /** 283 * @brief The factor of target to get fan rpm 284 */ 285 const double _factor; 286 287 /** 288 * @brief The offset of target to get fan rpm 289 */ 290 const int64_t _offset; 291 292 /** 293 * @brief The input speed, from the Value dbus property 294 */ 295 double _tachInput = 0; 296 297 /** 298 * @brief The current target speed, from the Target dbus property 299 * (if applicable) 300 */ 301 uint64_t _tachTarget = 0; 302 303 /** 304 * @brief The timeout value to use 305 */ 306 const size_t _timeout; 307 308 /** 309 * @brief Mode that current timer is in 310 */ 311 TimerMode _timerMode; 312 313 /** 314 * The timer object 315 */ 316 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> _timer; 317 318 /** 319 * @brief The match object for the Value properties changed signal 320 */ 321 std::unique_ptr<sdbusplus::server::match::match> tachSignal; 322 323 /** 324 * @brief The match object for the Target properties changed signal 325 */ 326 std::unique_ptr<sdbusplus::server::match::match> targetSignal; 327 328 /** 329 * @brief The number of seconds to wait between a sensor being set 330 * to nonfunctional and creating an error for it. 331 * 332 * If std::nullopt, no errors will be created. 333 */ 334 const std::optional<size_t> _errorDelay; 335 336 /** 337 * @brief The timer that uses _errorDelay. When it expires an error 338 * will be created for a faulted fan sensor (rotor). 339 * 340 * If _errorDelay is std::nullopt, then this won't be created. 341 */ 342 std::unique_ptr< 343 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>> 344 _errorTimer; 345 }; 346 347 } // namespace monitor 348 } // namespace fan 349 } // namespace phosphor 350