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 <experimental/filesystem> 18 #include <sdbusplus/bus.hpp> 19 #include <phosphor-logging/log.hpp> 20 #include <phosphor-logging/elog.hpp> 21 #include <phosphor-logging/elog-errors.hpp> 22 #include <xyz/openbmc_project/Common/error.hpp> 23 #include <unistd.h> 24 #include "config.h" 25 #include "manager.hpp" 26 #include "utility.hpp" 27 #include "sdbusplus.hpp" 28 29 namespace phosphor 30 { 31 namespace fan 32 { 33 namespace control 34 { 35 36 using namespace phosphor::logging; 37 namespace fs = std::experimental::filesystem; 38 39 constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1"; 40 constexpr auto SYSTEMD_OBJ_PATH = "/org/freedesktop/systemd1"; 41 constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager"; 42 constexpr auto FAN_CONTROL_READY_TARGET = "obmc-fan-control-ready@0.target"; 43 44 /** 45 * Check if a condition is true. Conditions are used to determine 46 * which fan zone to use. 47 * 48 * @param[in] bus - The D-Bus bus object 49 * @param[in] condition - The condition to check if true 50 * @return result - True if the condition is true 51 */ 52 bool checkCondition(sdbusplus::bus::bus& bus, const Condition& c) 53 { 54 auto& type = std::get<conditionTypePos>(c); 55 auto& properties = std::get<conditionPropertyListPos>(c); 56 57 for (auto& p : properties) 58 { 59 auto value = std::get<propertyValuePos>(p); 60 61 // TODO openbmc/openbmc#1769: Support more types than just getProperty. 62 if (type.compare("getProperty") == 0) 63 { 64 auto propertyValue = util::SDBusPlus::getProperty<decltype(value)>( 65 bus, 66 std::get<propertyPathPos>(p), 67 std::get<propertyInterfacePos>(p), 68 std::get<propertyNamePos>(p)); 69 70 if (value != propertyValue) 71 { 72 return false; 73 } 74 } 75 } 76 return true; 77 } 78 79 80 //Note: Future code will check 'mode' before starting control algorithm 81 Manager::Manager(sdbusplus::bus::bus& bus, 82 const sdeventplus::Event& event, 83 Mode mode) : 84 _bus(bus), 85 _objMgr(bus, CONTROL_OBJPATH) 86 { 87 //Create the appropriate Zone objects based on the 88 //actual system configuration. 89 90 //Find the 1 ZoneGroup that meets all of its conditions 91 for (auto& group : _zoneLayouts) 92 { 93 auto& conditions = std::get<conditionListPos>(group); 94 95 if (std::all_of(conditions.begin(), conditions.end(), 96 [&bus](const auto& condition) 97 { 98 return checkCondition(bus, condition); 99 })) 100 { 101 //Create a Zone object for each zone in this group 102 auto& zones = std::get<zoneListPos>(group); 103 104 for (auto& z : zones) 105 { 106 fs::path path{CONTROL_OBJPATH}; 107 path /= std::to_string(std::get<zoneNumPos>(z)); 108 _zones.emplace(std::get<zoneNumPos>(z), 109 std::make_unique<Zone>(mode, 110 _bus, 111 path.string(), 112 event, 113 z)); 114 } 115 116 break; 117 } 118 } 119 120 if (mode == Mode::control) 121 { 122 bus.request_name(CONTROL_BUSNAME); 123 } 124 } 125 126 127 void Manager::doInit() 128 { 129 for (auto& z : _zones) 130 { 131 z.second->setFullSpeed(); 132 } 133 134 auto delay = _powerOnDelay; 135 while (delay > 0) 136 { 137 delay = sleep(delay); 138 } 139 140 util::SDBusPlus::callMethod( 141 _bus, 142 SYSTEMD_SERVICE, 143 SYSTEMD_OBJ_PATH, 144 SYSTEMD_INTERFACE, 145 "StartUnit", 146 FAN_CONTROL_READY_TARGET, 147 "replace"); 148 } 149 150 } // namespace control 151 } // namespace fan 152 } // namespace phosphor 153