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
20bf8e56f6SMike Capps #include "dbus_paths.hpp"
213e1bb274SMatthew Barth #include "sdbusplus.hpp"
223e1bb274SMatthew Barth #include "utility.hpp"
233e1bb274SMatthew Barth
243e1bb274SMatthew Barth #include <unistd.h>
253e1bb274SMatthew Barth
263e1bb274SMatthew Barth #include <phosphor-logging/elog-errors.hpp>
273e1bb274SMatthew Barth #include <phosphor-logging/elog.hpp>
283e1bb274SMatthew Barth #include <phosphor-logging/log.hpp>
293e1bb274SMatthew Barth #include <sdbusplus/bus.hpp>
303e1bb274SMatthew Barth #include <xyz/openbmc_project/Common/error.hpp>
313e1bb274SMatthew Barth
3257352a31SMatt Spinler #include <algorithm>
332ea9a596SMatt Spinler #include <filesystem>
34e10416ecSMatt Spinler
35e10416ecSMatt Spinler namespace phosphor
36e10416ecSMatt Spinler {
37e10416ecSMatt Spinler namespace fan
38e10416ecSMatt Spinler {
39e10416ecSMatt Spinler namespace control
40e10416ecSMatt Spinler {
41e10416ecSMatt Spinler
42ee7f6428SMatt Spinler using namespace phosphor::logging;
432ea9a596SMatt Spinler namespace fs = std::filesystem;
44ee7f6428SMatt Spinler
45ee7f6428SMatt Spinler constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
46ee7f6428SMatt Spinler constexpr auto SYSTEMD_OBJ_PATH = "/org/freedesktop/systemd1";
47ee7f6428SMatt Spinler constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
48ee7f6428SMatt Spinler constexpr auto FAN_CONTROL_READY_TARGET = "obmc-fan-control-ready@0.target";
49ee7f6428SMatt Spinler
50f96b01e2SGunnar Mills /**
51f96b01e2SGunnar Mills * Check if a condition is true. Conditions are used to determine
52f96b01e2SGunnar Mills * which fan zone to use.
53f96b01e2SGunnar Mills *
54f96b01e2SGunnar Mills * @param[in] bus - The D-Bus bus object
55f96b01e2SGunnar Mills * @param[in] condition - The condition to check if true
56f96b01e2SGunnar Mills * @return result - True if the condition is true
57f96b01e2SGunnar Mills */
checkCondition(sdbusplus::bus_t & bus,const Condition & c)58cb356d48SPatrick Williams bool checkCondition(sdbusplus::bus_t& bus, const Condition& c)
59f96b01e2SGunnar Mills {
60f96b01e2SGunnar Mills auto& type = std::get<conditionTypePos>(c);
61f96b01e2SGunnar Mills auto& properties = std::get<conditionPropertyListPos>(c);
62f96b01e2SGunnar Mills
63f96b01e2SGunnar Mills for (auto& p : properties)
64f96b01e2SGunnar Mills {
65803d35bcSMatthew Barth auto value = std::get<propertyValuePos>(p);
66f96b01e2SGunnar Mills
67f96b01e2SGunnar Mills // TODO openbmc/openbmc#1769: Support more types than just getProperty.
68f96b01e2SGunnar Mills if (type.compare("getProperty") == 0)
69f96b01e2SGunnar Mills {
70803d35bcSMatthew Barth auto propertyValue = util::SDBusPlus::getProperty<decltype(value)>(
713e1bb274SMatthew Barth bus, std::get<propertyPathPos>(p),
72f96b01e2SGunnar Mills std::get<propertyInterfacePos>(p),
73803d35bcSMatthew Barth std::get<propertyNamePos>(p));
74f96b01e2SGunnar Mills
75f96b01e2SGunnar Mills if (value != propertyValue)
76f96b01e2SGunnar Mills {
77f96b01e2SGunnar Mills return false;
78f96b01e2SGunnar Mills }
79f96b01e2SGunnar Mills }
80f96b01e2SGunnar Mills }
81f96b01e2SGunnar Mills return true;
82f96b01e2SGunnar Mills }
83f96b01e2SGunnar Mills
84ee7f6428SMatt Spinler // Note: Future code will check 'mode' before starting control algorithm
Manager(sdbusplus::bus_t & bus,const sdeventplus::Event & event,Mode mode)85cb356d48SPatrick Williams Manager::Manager(sdbusplus::bus_t& bus, const sdeventplus::Event& event,
86*dfddd648SPatrick Williams Mode mode) : _bus(bus), _objMgr(bus, CONTROL_OBJPATH)
87e10416ecSMatt Spinler {
8857352a31SMatt Spinler // Create the appropriate Zone objects based on the
8957352a31SMatt Spinler // actual system configuration.
90f8ae7a5eSMatthew Barth
9157352a31SMatt Spinler // Find the 1 ZoneGroup that meets all of its conditions
92413e4d09SMatthew Barth for (auto& group : _zoneLayouts)
9357352a31SMatt Spinler {
9457352a31SMatt Spinler auto& conditions = std::get<conditionListPos>(group);
9557352a31SMatt Spinler
9657352a31SMatt Spinler if (std::all_of(conditions.begin(), conditions.end(),
973e1bb274SMatthew Barth [&bus](const auto& condition) {
98f96b01e2SGunnar Mills return checkCondition(bus, condition);
9957352a31SMatt Spinler }))
10057352a31SMatt Spinler {
10157352a31SMatt Spinler // Create a Zone object for each zone in this group
10257352a31SMatt Spinler auto& zones = std::get<zoneListPos>(group);
10357352a31SMatt Spinler
10457352a31SMatt Spinler for (auto& z : zones)
10557352a31SMatt Spinler {
10693af4194SMatthew Barth fs::path path{CONTROL_OBJPATH};
10793af4194SMatthew Barth path /= std::to_string(std::get<zoneNumPos>(z));
10857352a31SMatt Spinler _zones.emplace(std::get<zoneNumPos>(z),
1093e1bb274SMatthew Barth std::make_unique<Zone>(mode, _bus, path.string(),
1103e1bb274SMatthew Barth event, z));
11157352a31SMatt Spinler }
11257352a31SMatt Spinler
11357352a31SMatt Spinler break;
11457352a31SMatt Spinler }
11557352a31SMatt Spinler }
11657352a31SMatt Spinler
11793af4194SMatthew Barth if (mode == Mode::control)
11893af4194SMatthew Barth {
11914cc043fSMatthew Barth bus.request_name(CONTROL_BUSNAME);
120ee7f6428SMatt Spinler }
12193af4194SMatthew Barth }
122ee7f6428SMatt Spinler
doInit(const sdeventplus::Event &)123b2e9a4fcSMike Capps void Manager::doInit(const sdeventplus::Event& /*event*/)
124ee7f6428SMatt Spinler {
12557352a31SMatt Spinler for (auto& z : _zones)
12657352a31SMatt Spinler {
12757352a31SMatt Spinler z.second->setFullSpeed();
12857352a31SMatt Spinler }
129ee7f6428SMatt Spinler auto delay = _powerOnDelay;
130ee7f6428SMatt Spinler while (delay > 0)
131ee7f6428SMatt Spinler {
132ee7f6428SMatt Spinler delay = sleep(delay);
133e10416ecSMatt Spinler }
1342dc5abafSMatthew Barth
1353e1bb274SMatthew Barth util::SDBusPlus::callMethod(_bus, SYSTEMD_SERVICE, SYSTEMD_OBJ_PATH,
1363e1bb274SMatthew Barth SYSTEMD_INTERFACE, "StartUnit",
1373e1bb274SMatthew Barth FAN_CONTROL_READY_TARGET, "replace");
138ee7f6428SMatt Spinler }
139e10416ecSMatt Spinler
140f96b01e2SGunnar Mills } // namespace control
141f96b01e2SGunnar Mills } // namespace fan
142f96b01e2SGunnar Mills } // namespace phosphor
143