1 /** 2 * Copyright © 2017 IBM Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #include <algorithm> 17 #include <phosphor-logging/log.hpp> 18 #include <phosphor-logging/elog.hpp> 19 #include <phosphor-logging/elog-errors.hpp> 20 #include <xyz/openbmc_project/Common/error.hpp> 21 #include <unistd.h> 22 #include "manager.hpp" 23 #include "utility.hpp" 24 #include "sdbusplus.hpp" 25 26 namespace phosphor 27 { 28 namespace fan 29 { 30 namespace control 31 { 32 33 using namespace phosphor::logging; 34 35 constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1"; 36 constexpr auto SYSTEMD_OBJ_PATH = "/org/freedesktop/systemd1"; 37 constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager"; 38 constexpr auto FAN_CONTROL_READY_TARGET = "obmc-fan-control-ready@0.target"; 39 40 /** 41 * Check if a condition is true. Conditions are used to determine 42 * which fan zone to use. 43 * 44 * @param[in] bus - The D-Bus bus object 45 * @param[in] condition - The condition to check if true 46 * @return result - True if the condition is true 47 */ 48 bool checkCondition(sdbusplus::bus::bus& bus, const auto& c) 49 { 50 auto& type = std::get<conditionTypePos>(c); 51 auto& properties = std::get<conditionPropertyListPos>(c); 52 53 for (auto& p : properties) 54 { 55 auto value = std::get<propertyValuePos>(p); 56 57 // TODO openbmc/openbmc#1769: Support more types than just getProperty. 58 if (type.compare("getProperty") == 0) 59 { 60 auto propertyValue = util::SDBusPlus::getProperty<decltype(value)>( 61 bus, 62 std::get<propertyPathPos>(p), 63 std::get<propertyInterfacePos>(p), 64 std::get<propertyNamePos>(p)); 65 66 if (value != propertyValue) 67 { 68 return false; 69 } 70 } 71 } 72 return true; 73 } 74 75 76 //Note: Future code will check 'mode' before starting control algorithm 77 Manager::Manager(sdbusplus::bus::bus& bus, 78 const sdeventplus::Event& event, 79 Mode mode) : 80 _bus(bus) 81 { 82 //Create the appropriate Zone objects based on the 83 //actual system configuration. 84 85 //Find the 1 ZoneGroup that meets all of its conditions 86 for (auto& group : _zoneLayouts) 87 { 88 auto& conditions = std::get<conditionListPos>(group); 89 90 if (std::all_of(conditions.begin(), conditions.end(), 91 [&bus](const auto& condition) 92 { 93 return checkCondition(bus, condition); 94 })) 95 { 96 //Create a Zone object for each zone in this group 97 auto& zones = std::get<zoneListPos>(group); 98 99 for (auto& z : zones) 100 { 101 _zones.emplace(std::get<zoneNumPos>(z), 102 std::make_unique<Zone>(mode, _bus, event, z)); 103 } 104 105 break; 106 } 107 } 108 109 } 110 111 112 void Manager::doInit() 113 { 114 for (auto& z : _zones) 115 { 116 z.second->setFullSpeed(); 117 } 118 119 auto delay = _powerOnDelay; 120 while (delay > 0) 121 { 122 delay = sleep(delay); 123 } 124 125 util::SDBusPlus::callMethod( 126 _bus, 127 SYSTEMD_SERVICE, 128 SYSTEMD_OBJ_PATH, 129 SYSTEMD_INTERFACE, 130 "StartUnit", 131 FAN_CONTROL_READY_TARGET, 132 "replace"); 133 } 134 135 } // namespace control 136 } // namespace fan 137 } // namespace phosphor 138