1 #pragma once 2 #include <chrono> 3 #include <vector> 4 #include <cassert> 5 #include <algorithm> 6 #include <sdbusplus/bus.hpp> 7 #include "fan.hpp" 8 #include "types.hpp" 9 #include "timer.hpp" 10 11 namespace phosphor 12 { 13 namespace fan 14 { 15 namespace control 16 { 17 18 /** 19 * The mode fan control will run in: 20 * - init - only do the initialization steps 21 * - control - run normal control algorithms 22 */ 23 enum class Mode 24 { 25 init, 26 control 27 }; 28 29 /** 30 * @class Represents a fan control zone, which is a group of fans 31 * that behave the same. 32 */ 33 class Zone 34 { 35 public: 36 37 Zone() = delete; 38 Zone(const Zone&) = delete; 39 Zone(Zone&&) = delete; 40 Zone& operator=(const Zone&) = delete; 41 Zone& operator=(Zone&&) = delete; 42 ~Zone() = default; 43 44 /** 45 * Constructor 46 * Creates the appropriate fan objects based on 47 * the zone definition data passed in. 48 * 49 * @param[in] mode - mode of fan control 50 * @param[in] bus - the dbus object 51 * @param[in] events - sd_event pointer 52 * @param[in] def - the fan zone definition data 53 */ 54 Zone(Mode mode, 55 sdbusplus::bus::bus& bus, 56 phosphor::fan::event::EventPtr& events, 57 const ZoneDefinition& def); 58 59 /** 60 * Sets all fans in the zone to the speed 61 * passed in when the zone is active 62 * 63 * @param[in] speed - the fan speed 64 */ 65 void setSpeed(uint64_t speed); 66 67 /** 68 * Sets the zone to full speed regardless of zone's active state 69 */ 70 void setFullSpeed(); 71 72 /** 73 * @brief Sets the automatic fan control allowed active state 74 * 75 * @param[in] group - A group that affects the active state 76 * @param[in] isActiveAllow - Active state according to group 77 */ 78 void setActiveAllow(const Group* group, bool isActiveAllow); 79 80 /** 81 * @brief Sets the floor change allowed state 82 * 83 * @param[in] group - A group that affects floor changes 84 * @param[in] isAllow - Allow state according to group 85 */ 86 inline void setFloorChangeAllow(const Group* group, bool isAllow) 87 { 88 _floorChange[*(group)] = isAllow; 89 } 90 91 /** 92 * @brief Sets the decrease allowed state of a group 93 * 94 * @param[in] group - A group that affects speed decreases 95 * @param[in] isAllow - Allow state according to group 96 */ 97 inline void setDecreaseAllow(const Group* group, bool isAllow) 98 { 99 _decAllowed[*(group)] = isAllow; 100 } 101 102 /** 103 * @brief Sets a given object's property value 104 * 105 * @param[in] object - Name of the object containing the property 106 * @param[in] interface - Interface name containing the property 107 * @param[in] property - Property name 108 * @param[in] value - Property value 109 */ 110 template <typename T> 111 void setPropertyValue(const char* object, 112 const char* interface, 113 const char* property, 114 T value) 115 { 116 _properties[object][interface][property] = value; 117 }; 118 119 /** 120 * @brief Get the value of an object's property 121 * 122 * @param[in] object - Name of the object containing the property 123 * @param[in] interface - Interface name containing the property 124 * @param[in] property - Property name 125 * 126 * @return - The property value 127 */ 128 template <typename T> 129 inline auto getPropertyValue(const std::string& object, 130 const std::string& interface, 131 const std::string& property) 132 { 133 return sdbusplus::message::variant_ns::get<T>( 134 _properties.at(object).at(interface).at(property)); 135 }; 136 137 /** 138 * @brief Get the object's property variant 139 * 140 * @param[in] object - Name of the object containing the property 141 * @param[in] interface - Interface name containing the property 142 * @param[in] property - Property name 143 * 144 * @return - The property variant 145 */ 146 inline auto getPropValueVariant(const std::string& object, 147 const std::string& interface, 148 const std::string& property) 149 { 150 return _properties.at(object).at(interface).at(property); 151 }; 152 153 /** 154 * @brief Remove a service associated to a group 155 * 156 * @param[in] group - Group associated with service 157 * @param[in] name - Service name to remove 158 */ 159 void removeService(const Group* group, 160 const std::string& name); 161 162 /** 163 * @brief Set or update a service name owner in use 164 * 165 * @param[in] group - Group associated with service 166 * @param[in] name - Service name 167 * @param[in] hasOwner - Whether the service is owned or not 168 */ 169 void setServiceOwner(const Group* group, 170 const std::string& name, 171 const bool hasOwner); 172 173 /** 174 * @brief Set or update all services for a group 175 * 176 * @param[in] group - Group to get service names for 177 */ 178 void setServices(const Group* group); 179 180 /** 181 * @brief Get the group's list of service names 182 * 183 * @param[in] group - Group to get service names for 184 * 185 * @return - The list of service names 186 */ 187 inline auto getGroupServices(const Group* group) 188 { 189 return _services.at(*group); 190 } 191 192 /** 193 * @brief Initialize a set speed event properties and actions 194 * 195 * @param[in] event - Set speed event 196 */ 197 void initEvent(const SetSpeedEvent& event); 198 199 /** 200 * @brief Removes all the set speed event properties and actions 201 * 202 * @param[in] event - Set speed event 203 */ 204 void removeEvent(const SetSpeedEvent& event); 205 206 /** 207 * @brief Get the default floor speed 208 * 209 * @return - The defined default floor speed 210 */ 211 inline auto getDefFloor() 212 { 213 return _defFloorSpeed; 214 }; 215 216 /** 217 * @brief Get the ceiling speed 218 * 219 * @return - The current ceiling speed 220 */ 221 inline auto& getCeiling() const 222 { 223 return _ceilingSpeed; 224 }; 225 226 /** 227 * @brief Set the ceiling speed to the given speed 228 * 229 * @param[in] speed - Speed to set the ceiling to 230 */ 231 inline void setCeiling(uint64_t speed) 232 { 233 _ceilingSpeed = speed; 234 }; 235 236 /** 237 * @brief Swaps the ceiling key value with what's given and 238 * returns the value that was swapped. 239 * 240 * @param[in] keyValue - New ceiling key value 241 * 242 * @return - Ceiling key value prior to swapping 243 */ 244 inline auto swapCeilingKeyValue(int64_t keyValue) 245 { 246 std::swap(_ceilingKeyValue, keyValue); 247 return keyValue; 248 }; 249 250 /** 251 * @brief Get the increase speed delta 252 * 253 * @return - The current increase speed delta 254 */ 255 inline auto& getIncSpeedDelta() const 256 { 257 return _incSpeedDelta; 258 }; 259 260 /** 261 * @brief Get the decrease speed delta 262 * 263 * @return - The current decrease speed delta 264 */ 265 inline auto& getDecSpeedDelta() const 266 { 267 return _decSpeedDelta; 268 }; 269 270 /** 271 * @brief Set the floor speed to the given speed and increase target 272 * speed to the floor when target is below floor where floor changes 273 * are allowed. 274 * 275 * @param[in] speed - Speed to set the floor to 276 */ 277 void setFloor(uint64_t speed); 278 279 /** 280 * @brief Set the requested speed base to be used as the speed to 281 * base a new requested speed target from 282 * 283 * @param[in] speedBase - Base speed value to use 284 */ 285 inline void setRequestSpeedBase(uint64_t speedBase) 286 { 287 _requestSpeedBase = speedBase; 288 }; 289 290 /** 291 * @brief Calculate the requested target speed from the given delta 292 * and increase the fan speeds, not going above the ceiling. 293 * 294 * @param[in] targetDelta - The delta to increase the target speed by 295 */ 296 void requestSpeedIncrease(uint64_t targetDelta); 297 298 /** 299 * @brief Calculate the requested target speed from the given delta 300 * and increase the fan speeds, not going above the ceiling. 301 * 302 * @param[in] targetDelta - The delta to increase the target speed by 303 */ 304 void requestSpeedDecrease(uint64_t targetDelta); 305 306 /** 307 * @brief Callback function for the increase timer that delays 308 * processing of requested speed increases while fans are increasing 309 */ 310 void incTimerExpired(); 311 312 /** 313 * @brief Callback function for the decrease timer that processes any 314 * requested speed decreases if allowed 315 */ 316 void decTimerExpired(); 317 318 /** 319 * @brief Get the event pointer used with this zone's timers 320 * 321 * @return - The Dbus event pointer for timers 322 */ 323 inline auto& getEventPtr() 324 { 325 return _sdEvents; 326 } 327 328 /** 329 * @brief Get the list of timer events 330 * 331 * @return - List of timer events 332 */ 333 inline auto& getTimerEvents() 334 { 335 return _timerEvents; 336 } 337 338 /** 339 * @brief Find the first instance of a timer event 340 * 341 * @param[in] eventGroup - Group associated with a timer 342 * @param[in] eventActions - List of actions associated with a timer 343 * 344 * @return - Iterator to the timer event 345 */ 346 std::vector<TimerEvent>::iterator findTimer( 347 const Group& eventGroup, 348 const std::vector<Action>& eventActions); 349 350 /** 351 * @brief Add a timer to the list of timer based events 352 * 353 * @param[in] data - Event data for timer 354 * @param[in] timer - Timer to be added 355 */ 356 inline void addTimer( 357 std::unique_ptr<EventData>&& data, 358 std::unique_ptr<phosphor::fan::util::Timer>&& timer) 359 { 360 _timerEvents.emplace_back(std::move(data), std::move(timer)); 361 }; 362 363 /** 364 * @brief Remove the given timer event 365 * 366 * @param[in] teIter - Iterator pointing to the timer event to remove 367 */ 368 inline void removeTimer(std::vector<TimerEvent>::iterator& teIter) 369 { 370 assert(teIter != std::end(_timerEvents)); 371 std::get<timerEventDataPos>(*teIter).reset(); 372 std::get<timerTimerPos>(*teIter).reset(); 373 _timerEvents.erase(teIter); 374 } 375 376 /** 377 * @brief Callback function for event timers that processes the given 378 * actions for a group 379 * 380 * @param[in] eventGroup - Group to process actions on 381 * @param[in] eventActions - List of event actions to run 382 */ 383 void timerExpired(Group eventGroup, std::vector<Action> eventActions); 384 385 private: 386 387 /** 388 * The dbus object 389 */ 390 sdbusplus::bus::bus& _bus; 391 392 /** 393 * Full speed for the zone 394 */ 395 const uint64_t _fullSpeed; 396 397 /** 398 * The zone number 399 */ 400 const size_t _zoneNum; 401 402 /** 403 * The default floor speed for the zone 404 */ 405 const uint64_t _defFloorSpeed; 406 407 /** 408 * The default ceiling speed for the zone 409 */ 410 const uint64_t _defCeilingSpeed; 411 412 /** 413 * The floor speed to not go below 414 */ 415 uint64_t _floorSpeed = _defFloorSpeed; 416 417 /** 418 * The ceiling speed to not go above 419 */ 420 uint64_t _ceilingSpeed = _defCeilingSpeed; 421 422 /** 423 * The previous sensor value for calculating the ceiling 424 */ 425 int64_t _ceilingKeyValue = 0; 426 427 /** 428 * Automatic fan control active state 429 */ 430 bool _isActive = true; 431 432 /** 433 * Target speed for this zone 434 */ 435 uint64_t _targetSpeed = _fullSpeed; 436 437 /** 438 * Speed increase delta 439 */ 440 uint64_t _incSpeedDelta = 0; 441 442 /** 443 * Speed decrease delta 444 */ 445 uint64_t _decSpeedDelta = 0; 446 447 /** 448 * Requested speed base 449 */ 450 uint64_t _requestSpeedBase = 0; 451 452 /** 453 * Speed increase delay in seconds 454 */ 455 std::chrono::seconds _incDelay; 456 457 /** 458 * Speed decrease interval in seconds 459 */ 460 std::chrono::seconds _decInterval; 461 462 /** 463 * The increase timer object 464 */ 465 phosphor::fan::util::Timer _incTimer; 466 467 /** 468 * The decrease timer object 469 */ 470 phosphor::fan::util::Timer _decTimer; 471 472 /** 473 * Dbus event used on set speed event timers 474 */ 475 phosphor::fan::event::EventPtr& _sdEvents; 476 477 /** 478 * The vector of fans in this zone 479 */ 480 std::vector<std::unique_ptr<Fan>> _fans; 481 482 /** 483 * @brief Map of object property values 484 */ 485 std::map<std::string, 486 std::map<std::string, 487 std::map<std::string, 488 PropertyVariantType>>> _properties; 489 490 /** 491 * @brief Map of active fan control allowed by groups 492 */ 493 std::map<const Group, bool> _active; 494 495 /** 496 * @brief Map of floor change allowed by groups 497 */ 498 std::map<const Group, bool> _floorChange; 499 500 /** 501 * @brief Map of groups controlling decreases allowed 502 */ 503 std::map<const Group, bool> _decAllowed; 504 505 /** 506 * @brief Map of group service names 507 */ 508 std::map<const Group, std::vector<Service>> _services; 509 510 /** 511 * @brief List of signal event arguments and Dbus matches for callbacks 512 */ 513 std::vector<SignalEvent> _signalEvents; 514 515 /** 516 * @brief List of timers for events 517 */ 518 std::vector<TimerEvent> _timerEvents; 519 520 /** 521 * @brief Get the request speed base if defined, otherwise the 522 * the current target speed is returned 523 * 524 * @return - The request speed base or current target speed 525 */ 526 inline auto getRequestSpeedBase() const 527 { 528 return (_requestSpeedBase != 0) ? _requestSpeedBase : _targetSpeed; 529 }; 530 531 /** 532 * @brief Dbus signal change callback handler 533 * 534 * @param[in] msg - Expanded sdbusplus message data 535 * @param[in] eventData - The single event's data 536 */ 537 void handleEvent(sdbusplus::message::message& msg, 538 const EventData* eventData); 539 }; 540 541 } 542 } 543 } 544