1e10416ecSMatt Spinler /** 2e10416ecSMatt Spinler * Copyright © 2017 IBM Corporation 3e10416ecSMatt Spinler * 4e10416ecSMatt Spinler * Licensed under the Apache License, Version 2.0 (the "License"); 5e10416ecSMatt Spinler * you may not use this file except in compliance with the License. 6e10416ecSMatt Spinler * You may obtain a copy of the License at 7e10416ecSMatt Spinler * 8e10416ecSMatt Spinler * http://www.apache.org/licenses/LICENSE-2.0 9e10416ecSMatt Spinler * 10e10416ecSMatt Spinler * Unless required by applicable law or agreed to in writing, software 11e10416ecSMatt Spinler * distributed under the License is distributed on an "AS IS" BASIS, 12e10416ecSMatt Spinler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e10416ecSMatt Spinler * See the License for the specific language governing permissions and 14e10416ecSMatt Spinler * limitations under the License. 15e10416ecSMatt Spinler */ 1657352a31SMatt Spinler #include <algorithm> 17ee7f6428SMatt Spinler #include <phosphor-logging/log.hpp> 18618027abSDinesh Chinari #include <phosphor-logging/elog.hpp> 19618027abSDinesh Chinari #include <phosphor-logging/elog-errors.hpp> 20618027abSDinesh Chinari #include <xyz/openbmc_project/Common/error.hpp> 21ee7f6428SMatt Spinler #include <unistd.h> 22e10416ecSMatt Spinler #include "manager.hpp" 23f96b01e2SGunnar Mills #include "utility.hpp" 24*803d35bcSMatthew Barth #include "sdbusplus.hpp" 25e10416ecSMatt Spinler 26e10416ecSMatt Spinler namespace phosphor 27e10416ecSMatt Spinler { 28e10416ecSMatt Spinler namespace fan 29e10416ecSMatt Spinler { 30e10416ecSMatt Spinler namespace control 31e10416ecSMatt Spinler { 32e10416ecSMatt Spinler 33ee7f6428SMatt Spinler using namespace phosphor::logging; 34ee7f6428SMatt Spinler 35ee7f6428SMatt Spinler constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1"; 36ee7f6428SMatt Spinler constexpr auto SYSTEMD_OBJ_PATH = "/org/freedesktop/systemd1"; 37ee7f6428SMatt Spinler constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager"; 38ee7f6428SMatt Spinler constexpr auto FAN_CONTROL_READY_TARGET = "obmc-fan-control-ready@0.target"; 39ee7f6428SMatt Spinler 40f96b01e2SGunnar Mills /** 41f96b01e2SGunnar Mills * Check if a condition is true. Conditions are used to determine 42f96b01e2SGunnar Mills * which fan zone to use. 43f96b01e2SGunnar Mills * 44f96b01e2SGunnar Mills * @param[in] bus - The D-Bus bus object 45f96b01e2SGunnar Mills * @param[in] condition - The condition to check if true 46f96b01e2SGunnar Mills * @return result - True if the condition is true 47f96b01e2SGunnar Mills */ 48f96b01e2SGunnar Mills bool checkCondition(sdbusplus::bus::bus& bus, const auto& c) 49f96b01e2SGunnar Mills { 50f96b01e2SGunnar Mills auto& type = std::get<conditionTypePos>(c); 51f96b01e2SGunnar Mills auto& properties = std::get<conditionPropertyListPos>(c); 52f96b01e2SGunnar Mills 53f96b01e2SGunnar Mills for (auto& p : properties) 54f96b01e2SGunnar Mills { 55*803d35bcSMatthew Barth auto value = std::get<propertyValuePos>(p); 56f96b01e2SGunnar Mills 57f96b01e2SGunnar Mills // TODO openbmc/openbmc#1769: Support more types than just getProperty. 58f96b01e2SGunnar Mills if (type.compare("getProperty") == 0) 59f96b01e2SGunnar Mills { 60*803d35bcSMatthew Barth auto propertyValue = util::SDBusPlus::getProperty<decltype(value)>( 61*803d35bcSMatthew Barth bus, 62f96b01e2SGunnar Mills std::get<propertyPathPos>(p), 63f96b01e2SGunnar Mills std::get<propertyInterfacePos>(p), 64*803d35bcSMatthew Barth std::get<propertyNamePos>(p)); 65f96b01e2SGunnar Mills 66f96b01e2SGunnar Mills if (value != propertyValue) 67f96b01e2SGunnar Mills { 68f96b01e2SGunnar Mills return false; 69f96b01e2SGunnar Mills } 70f96b01e2SGunnar Mills } 71f96b01e2SGunnar Mills } 72f96b01e2SGunnar Mills return true; 73f96b01e2SGunnar Mills } 74f96b01e2SGunnar Mills 75f96b01e2SGunnar Mills 76ee7f6428SMatt Spinler //Note: Future code will check 'mode' before starting control algorithm 77ee7f6428SMatt Spinler Manager::Manager(sdbusplus::bus::bus& bus, 788600d9a0SMatthew Barth phosphor::fan::event::EventPtr& events, 79ee7f6428SMatt Spinler Mode mode) : 80e10416ecSMatt Spinler _bus(bus) 81e10416ecSMatt Spinler { 8257352a31SMatt Spinler //Create the appropriate Zone objects based on the 8357352a31SMatt Spinler //actual system configuration. 8457352a31SMatt Spinler 8557352a31SMatt Spinler //Find the 1 ZoneGroup that meets all of its conditions 8657352a31SMatt Spinler for (auto& group : _zoneLayouts) 8757352a31SMatt Spinler { 8857352a31SMatt Spinler auto& conditions = std::get<conditionListPos>(group); 8957352a31SMatt Spinler 9057352a31SMatt Spinler if (std::all_of(conditions.begin(), conditions.end(), 91f96b01e2SGunnar Mills [&bus](const auto& condition) 9257352a31SMatt Spinler { 93f96b01e2SGunnar Mills return checkCondition(bus, condition); 9457352a31SMatt Spinler })) 9557352a31SMatt Spinler { 9657352a31SMatt Spinler //Create a Zone object for each zone in this group 9757352a31SMatt Spinler auto& zones = std::get<zoneListPos>(group); 9857352a31SMatt Spinler 9957352a31SMatt Spinler for (auto& z : zones) 10057352a31SMatt Spinler { 10157352a31SMatt Spinler _zones.emplace(std::get<zoneNumPos>(z), 1028600d9a0SMatthew Barth std::make_unique<Zone>(mode, _bus, events, z)); 10357352a31SMatt Spinler } 10457352a31SMatt Spinler 10557352a31SMatt Spinler break; 10657352a31SMatt Spinler } 10757352a31SMatt Spinler } 10857352a31SMatt Spinler 109ee7f6428SMatt Spinler } 110ee7f6428SMatt Spinler 111ee7f6428SMatt Spinler 112ee7f6428SMatt Spinler void Manager::doInit() 113ee7f6428SMatt Spinler { 11457352a31SMatt Spinler for (auto& z : _zones) 11557352a31SMatt Spinler { 11657352a31SMatt Spinler z.second->setFullSpeed(); 11757352a31SMatt Spinler } 118ee7f6428SMatt Spinler 119ee7f6428SMatt Spinler auto delay = _powerOnDelay; 120ee7f6428SMatt Spinler while (delay > 0) 121ee7f6428SMatt Spinler { 122ee7f6428SMatt Spinler delay = sleep(delay); 123e10416ecSMatt Spinler } 124e10416ecSMatt Spinler 125ee7f6428SMatt Spinler startFanControlReadyTarget(); 126ee7f6428SMatt Spinler } 127ee7f6428SMatt Spinler 128ee7f6428SMatt Spinler 129ee7f6428SMatt Spinler void Manager::startFanControlReadyTarget() 130ee7f6428SMatt Spinler { 131ee7f6428SMatt Spinler auto method = _bus.new_method_call(SYSTEMD_SERVICE, 132ee7f6428SMatt Spinler SYSTEMD_OBJ_PATH, 133ee7f6428SMatt Spinler SYSTEMD_INTERFACE, 134ee7f6428SMatt Spinler "StartUnit"); 135ee7f6428SMatt Spinler 136ee7f6428SMatt Spinler method.append(FAN_CONTROL_READY_TARGET); 137ee7f6428SMatt Spinler method.append("replace"); 138ee7f6428SMatt Spinler 139ee7f6428SMatt Spinler auto response = _bus.call(method); 140ee7f6428SMatt Spinler if (response.is_method_error()) 141ee7f6428SMatt Spinler { 142ee7f6428SMatt Spinler log<level::ERR>("Failed to start fan control ready target"); 143618027abSDinesh Chinari elog<InternalFailure>(); 144ee7f6428SMatt Spinler } 145ee7f6428SMatt Spinler } 146e10416ecSMatt Spinler 147f96b01e2SGunnar Mills } // namespace control 148f96b01e2SGunnar Mills } // namespace fan 149f96b01e2SGunnar Mills } // namespace phosphor 150