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