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 */ 163e1bb274SMatthew Barth #include "config.h" 173e1bb274SMatthew Barth 183e1bb274SMatthew Barth #include "manager.hpp" 193e1bb274SMatthew Barth 203e1bb274SMatthew Barth #include "sdbusplus.hpp" 213e1bb274SMatthew Barth #include "utility.hpp" 2223ac24c1SMatthew Barth #ifdef CONTROL_USE_JSON 2323ac24c1SMatthew Barth #include "json_parser.hpp" 2423ac24c1SMatthew Barth #endif 253e1bb274SMatthew Barth 263e1bb274SMatthew Barth #include <unistd.h> 273e1bb274SMatthew Barth 283e1bb274SMatthew Barth #include <phosphor-logging/elog-errors.hpp> 293e1bb274SMatthew Barth #include <phosphor-logging/elog.hpp> 303e1bb274SMatthew Barth #include <phosphor-logging/log.hpp> 313e1bb274SMatthew Barth #include <sdbusplus/bus.hpp> 323e1bb274SMatthew Barth #include <xyz/openbmc_project/Common/error.hpp> 333e1bb274SMatthew Barth 3457352a31SMatt Spinler #include <algorithm> 3593af4194SMatthew Barth #include <experimental/filesystem> 36e10416ecSMatt Spinler 37e10416ecSMatt Spinler namespace phosphor 38e10416ecSMatt Spinler { 39e10416ecSMatt Spinler namespace fan 40e10416ecSMatt Spinler { 41e10416ecSMatt Spinler namespace control 42e10416ecSMatt Spinler { 43e10416ecSMatt Spinler 44ee7f6428SMatt Spinler using namespace phosphor::logging; 4593af4194SMatthew Barth namespace fs = std::experimental::filesystem; 46ee7f6428SMatt Spinler 47ee7f6428SMatt Spinler constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1"; 48ee7f6428SMatt Spinler constexpr auto SYSTEMD_OBJ_PATH = "/org/freedesktop/systemd1"; 49ee7f6428SMatt Spinler constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager"; 50ee7f6428SMatt Spinler constexpr auto FAN_CONTROL_READY_TARGET = "obmc-fan-control-ready@0.target"; 51ee7f6428SMatt Spinler 52f96b01e2SGunnar Mills /** 53f96b01e2SGunnar Mills * Check if a condition is true. Conditions are used to determine 54f96b01e2SGunnar Mills * which fan zone to use. 55f96b01e2SGunnar Mills * 56f96b01e2SGunnar Mills * @param[in] bus - The D-Bus bus object 57f96b01e2SGunnar Mills * @param[in] condition - The condition to check if true 58f96b01e2SGunnar Mills * @return result - True if the condition is true 59f96b01e2SGunnar Mills */ 60f0b020fbSBrad Bishop bool checkCondition(sdbusplus::bus::bus& bus, const Condition& c) 61f96b01e2SGunnar Mills { 62f96b01e2SGunnar Mills auto& type = std::get<conditionTypePos>(c); 63f96b01e2SGunnar Mills auto& properties = std::get<conditionPropertyListPos>(c); 64f96b01e2SGunnar Mills 65f96b01e2SGunnar Mills for (auto& p : properties) 66f96b01e2SGunnar Mills { 67803d35bcSMatthew Barth auto value = std::get<propertyValuePos>(p); 68f96b01e2SGunnar Mills 69f96b01e2SGunnar Mills // TODO openbmc/openbmc#1769: Support more types than just getProperty. 70f96b01e2SGunnar Mills if (type.compare("getProperty") == 0) 71f96b01e2SGunnar Mills { 72803d35bcSMatthew Barth auto propertyValue = util::SDBusPlus::getProperty<decltype(value)>( 733e1bb274SMatthew Barth bus, std::get<propertyPathPos>(p), 74f96b01e2SGunnar Mills std::get<propertyInterfacePos>(p), 75803d35bcSMatthew Barth std::get<propertyNamePos>(p)); 76f96b01e2SGunnar Mills 77f96b01e2SGunnar Mills if (value != propertyValue) 78f96b01e2SGunnar Mills { 79f96b01e2SGunnar Mills return false; 80f96b01e2SGunnar Mills } 81f96b01e2SGunnar Mills } 82f96b01e2SGunnar Mills } 83f96b01e2SGunnar Mills return true; 84f96b01e2SGunnar Mills } 85f96b01e2SGunnar Mills 86ee7f6428SMatt Spinler // Note: Future code will check 'mode' before starting control algorithm 873e1bb274SMatthew Barth Manager::Manager(sdbusplus::bus::bus& bus, const sdeventplus::Event& event, 88ee7f6428SMatt Spinler Mode mode) : 8993af4194SMatthew Barth _bus(bus), 9093af4194SMatthew Barth _objMgr(bus, CONTROL_OBJPATH) 91e10416ecSMatt Spinler { 9257352a31SMatt Spinler // Create the appropriate Zone objects based on the 9357352a31SMatt Spinler // actual system configuration. 9423ac24c1SMatthew Barth #ifdef CONTROL_USE_JSON 9523ac24c1SMatthew Barth auto zoneLayouts = getZoneGroups(bus); 9623ac24c1SMatthew Barth #else 9723ac24c1SMatthew Barth auto zoneLayouts = _zoneLayouts; 9823ac24c1SMatthew Barth #endif 9957352a31SMatt Spinler 10057352a31SMatt Spinler // Find the 1 ZoneGroup that meets all of its conditions 10123ac24c1SMatthew Barth for (auto& group : zoneLayouts) 10257352a31SMatt Spinler { 10357352a31SMatt Spinler auto& conditions = std::get<conditionListPos>(group); 10457352a31SMatt Spinler 10557352a31SMatt Spinler if (std::all_of(conditions.begin(), conditions.end(), 1063e1bb274SMatthew Barth [&bus](const auto& condition) { 107f96b01e2SGunnar Mills return checkCondition(bus, condition); 10857352a31SMatt Spinler })) 10957352a31SMatt Spinler { 11057352a31SMatt Spinler // Create a Zone object for each zone in this group 11157352a31SMatt Spinler auto& zones = std::get<zoneListPos>(group); 11257352a31SMatt Spinler 11357352a31SMatt Spinler for (auto& z : zones) 11457352a31SMatt Spinler { 11593af4194SMatthew Barth fs::path path{CONTROL_OBJPATH}; 11693af4194SMatthew Barth path /= std::to_string(std::get<zoneNumPos>(z)); 11757352a31SMatt Spinler _zones.emplace(std::get<zoneNumPos>(z), 1183e1bb274SMatthew Barth std::make_unique<Zone>(mode, _bus, path.string(), 1193e1bb274SMatthew Barth event, z)); 12057352a31SMatt Spinler } 12157352a31SMatt Spinler 12257352a31SMatt Spinler break; 12357352a31SMatt Spinler } 12457352a31SMatt Spinler } 12557352a31SMatt Spinler 12693af4194SMatthew Barth if (mode == Mode::control) 12793af4194SMatthew Barth { 12814cc043fSMatthew Barth bus.request_name(CONTROL_BUSNAME); 129ee7f6428SMatt Spinler } 13093af4194SMatthew Barth } 131ee7f6428SMatt Spinler 132ee7f6428SMatt Spinler void Manager::doInit() 133ee7f6428SMatt Spinler { 13457352a31SMatt Spinler for (auto& z : _zones) 13557352a31SMatt Spinler { 13657352a31SMatt Spinler z.second->setFullSpeed(); 13757352a31SMatt Spinler } 138*2dc5abafSMatthew Barth #ifdef CONTROL_USE_JSON 139*2dc5abafSMatthew Barth auto delay = getPowerOnDelay(_bus); 140*2dc5abafSMatthew Barth #else 141ee7f6428SMatt Spinler auto delay = _powerOnDelay; 142*2dc5abafSMatthew Barth #endif 143ee7f6428SMatt Spinler while (delay > 0) 144ee7f6428SMatt Spinler { 145ee7f6428SMatt Spinler delay = sleep(delay); 146e10416ecSMatt Spinler } 147*2dc5abafSMatthew Barth 1483e1bb274SMatthew Barth util::SDBusPlus::callMethod(_bus, SYSTEMD_SERVICE, SYSTEMD_OBJ_PATH, 1493e1bb274SMatthew Barth SYSTEMD_INTERFACE, "StartUnit", 1503e1bb274SMatthew Barth FAN_CONTROL_READY_TARGET, "replace"); 151ee7f6428SMatt Spinler } 152e10416ecSMatt Spinler 153f96b01e2SGunnar Mills } // namespace control 154f96b01e2SGunnar Mills } // namespace fan 155f96b01e2SGunnar Mills } // namespace phosphor 156