xref: /openbmc/phosphor-fan-presence/control/manager.cpp (revision f96b01e28462a78d253c0917cd201a7f094026c8)
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>
18ee7f6428SMatt Spinler #include <unistd.h>
19e10416ecSMatt Spinler #include "manager.hpp"
20*f96b01e2SGunnar Mills #include "utility.hpp"
21e10416ecSMatt Spinler 
22e10416ecSMatt Spinler namespace phosphor
23e10416ecSMatt Spinler {
24e10416ecSMatt Spinler namespace fan
25e10416ecSMatt Spinler {
26e10416ecSMatt Spinler namespace control
27e10416ecSMatt Spinler {
28e10416ecSMatt Spinler 
29ee7f6428SMatt Spinler using namespace phosphor::logging;
30ee7f6428SMatt Spinler 
31ee7f6428SMatt Spinler constexpr auto SYSTEMD_SERVICE   = "org.freedesktop.systemd1";
32ee7f6428SMatt Spinler constexpr auto SYSTEMD_OBJ_PATH  = "/org/freedesktop/systemd1";
33ee7f6428SMatt Spinler constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
34ee7f6428SMatt Spinler constexpr auto FAN_CONTROL_READY_TARGET = "obmc-fan-control-ready@0.target";
35ee7f6428SMatt Spinler 
36*f96b01e2SGunnar Mills constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
37*f96b01e2SGunnar Mills constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
38*f96b01e2SGunnar Mills constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper";
39*f96b01e2SGunnar Mills constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper";
40*f96b01e2SGunnar Mills 
41*f96b01e2SGunnar Mills 
42*f96b01e2SGunnar Mills /**
43*f96b01e2SGunnar Mills  * Get the current value of the D-Bus property under the specified path
44*f96b01e2SGunnar Mills  * and interface.
45*f96b01e2SGunnar Mills  *
46*f96b01e2SGunnar Mills  * @param[in] bus          - The D-Bus bus object
47*f96b01e2SGunnar Mills  * @param[in] path         - The D-Bus path
48*f96b01e2SGunnar Mills  * @param[in] interface    - The D-Bus interface
49*f96b01e2SGunnar Mills  * @param[in] propertyName - The D-Bus property
50*f96b01e2SGunnar Mills  * @param[out] value       - The D-Bus property's value
51*f96b01e2SGunnar Mills  */
52*f96b01e2SGunnar Mills template <typename T>
53*f96b01e2SGunnar Mills void getProperty(sdbusplus::bus::bus& bus,
54*f96b01e2SGunnar Mills                  const std::string& path,
55*f96b01e2SGunnar Mills                  const std::string& interface,
56*f96b01e2SGunnar Mills                  const std::string& propertyName,
57*f96b01e2SGunnar Mills                  T& value)
58*f96b01e2SGunnar Mills {
59*f96b01e2SGunnar Mills     sdbusplus::message::variant<T> property;
60*f96b01e2SGunnar Mills     std::string service = phosphor::fan::util::getService(path, interface, bus);
61*f96b01e2SGunnar Mills 
62*f96b01e2SGunnar Mills     auto method = bus.new_method_call(service.c_str(),
63*f96b01e2SGunnar Mills                                       path.c_str(),
64*f96b01e2SGunnar Mills                                       PROPERTY_INTERFACE,
65*f96b01e2SGunnar Mills                                       "Get");
66*f96b01e2SGunnar Mills 
67*f96b01e2SGunnar Mills     method.append(interface, propertyName);
68*f96b01e2SGunnar Mills     auto reply = bus.call(method);
69*f96b01e2SGunnar Mills 
70*f96b01e2SGunnar Mills     if (reply.is_method_error())
71*f96b01e2SGunnar Mills     {
72*f96b01e2SGunnar Mills         throw std::runtime_error(
73*f96b01e2SGunnar Mills             "Error in call response for retrieving property");
74*f96b01e2SGunnar Mills     }
75*f96b01e2SGunnar Mills     reply.read(property);
76*f96b01e2SGunnar Mills     value = sdbusplus::message::variant_ns::get<T>(property);
77*f96b01e2SGunnar Mills }
78*f96b01e2SGunnar Mills 
79*f96b01e2SGunnar Mills 
80*f96b01e2SGunnar Mills /**
81*f96b01e2SGunnar Mills  * Check if a condition is true. Conditions are used to determine
82*f96b01e2SGunnar Mills  * which fan zone to use.
83*f96b01e2SGunnar Mills  *
84*f96b01e2SGunnar Mills  * @param[in] bus       - The D-Bus bus object
85*f96b01e2SGunnar Mills  * @param[in] condition - The condition to check if true
86*f96b01e2SGunnar Mills  * @return result       - True if the condition is true
87*f96b01e2SGunnar Mills  */
88*f96b01e2SGunnar Mills bool checkCondition(sdbusplus::bus::bus& bus, const auto& c)
89*f96b01e2SGunnar Mills {
90*f96b01e2SGunnar Mills     auto& type = std::get<conditionTypePos>(c);
91*f96b01e2SGunnar Mills     auto& properties = std::get<conditionPropertyListPos>(c);
92*f96b01e2SGunnar Mills 
93*f96b01e2SGunnar Mills     for (auto& p : properties)
94*f96b01e2SGunnar Mills     {
95*f96b01e2SGunnar Mills         bool value = std::get<propertyValuePos>(p);
96*f96b01e2SGunnar Mills         bool propertyValue;
97*f96b01e2SGunnar Mills 
98*f96b01e2SGunnar Mills         // TODO openbmc/openbmc#1769: Support more types than just getProperty.
99*f96b01e2SGunnar Mills         if (type.compare("getProperty") == 0)
100*f96b01e2SGunnar Mills         {
101*f96b01e2SGunnar Mills             getProperty(bus,
102*f96b01e2SGunnar Mills                         std::get<propertyPathPos>(p),
103*f96b01e2SGunnar Mills                         std::get<propertyInterfacePos>(p),
104*f96b01e2SGunnar Mills                         std::get<propertyNamePos>(p),
105*f96b01e2SGunnar Mills                         propertyValue);
106*f96b01e2SGunnar Mills 
107*f96b01e2SGunnar Mills             if (value != propertyValue)
108*f96b01e2SGunnar Mills             {
109*f96b01e2SGunnar Mills                 return false;
110*f96b01e2SGunnar Mills             }
111*f96b01e2SGunnar Mills         }
112*f96b01e2SGunnar Mills     }
113*f96b01e2SGunnar Mills     return true;
114*f96b01e2SGunnar Mills }
115*f96b01e2SGunnar Mills 
116*f96b01e2SGunnar Mills 
117ee7f6428SMatt Spinler //Note: Future code will check 'mode' before starting control algorithm
118ee7f6428SMatt Spinler Manager::Manager(sdbusplus::bus::bus& bus,
119ee7f6428SMatt Spinler                  Mode mode) :
120e10416ecSMatt Spinler     _bus(bus)
121e10416ecSMatt Spinler {
12257352a31SMatt Spinler     //Create the appropriate Zone objects based on the
12357352a31SMatt Spinler     //actual system configuration.
12457352a31SMatt Spinler 
12557352a31SMatt Spinler     //Find the 1 ZoneGroup that meets all of its conditions
12657352a31SMatt Spinler     for (auto& group : _zoneLayouts)
12757352a31SMatt Spinler     {
12857352a31SMatt Spinler         auto& conditions = std::get<conditionListPos>(group);
12957352a31SMatt Spinler 
13057352a31SMatt Spinler         if (std::all_of(conditions.begin(), conditions.end(),
131*f96b01e2SGunnar Mills                         [&bus](const auto& condition)
13257352a31SMatt Spinler         {
133*f96b01e2SGunnar Mills             return checkCondition(bus, condition);
13457352a31SMatt Spinler         }))
13557352a31SMatt Spinler         {
13657352a31SMatt Spinler             //Create a Zone object for each zone in this group
13757352a31SMatt Spinler             auto& zones = std::get<zoneListPos>(group);
13857352a31SMatt Spinler 
13957352a31SMatt Spinler             for (auto& z : zones)
14057352a31SMatt Spinler             {
14157352a31SMatt Spinler                 _zones.emplace(std::get<zoneNumPos>(z),
14214184131SMatthew Barth                                std::make_unique<Zone>(mode, _bus, z));
14357352a31SMatt Spinler             }
14457352a31SMatt Spinler 
14557352a31SMatt Spinler             break;
14657352a31SMatt Spinler         }
14757352a31SMatt Spinler     }
14857352a31SMatt Spinler 
149ee7f6428SMatt Spinler }
150ee7f6428SMatt Spinler 
151ee7f6428SMatt Spinler 
152ee7f6428SMatt Spinler void Manager::doInit()
153ee7f6428SMatt Spinler {
15457352a31SMatt Spinler     for (auto& z : _zones)
15557352a31SMatt Spinler     {
15657352a31SMatt Spinler         z.second->setFullSpeed();
15757352a31SMatt Spinler     }
158ee7f6428SMatt Spinler 
159ee7f6428SMatt Spinler     auto delay = _powerOnDelay;
160ee7f6428SMatt Spinler     while (delay > 0)
161ee7f6428SMatt Spinler     {
162ee7f6428SMatt Spinler         delay = sleep(delay);
163e10416ecSMatt Spinler     }
164e10416ecSMatt Spinler 
165ee7f6428SMatt Spinler     startFanControlReadyTarget();
166ee7f6428SMatt Spinler }
167ee7f6428SMatt Spinler 
168ee7f6428SMatt Spinler 
169ee7f6428SMatt Spinler void Manager::startFanControlReadyTarget()
170ee7f6428SMatt Spinler {
171ee7f6428SMatt Spinler     auto method = _bus.new_method_call(SYSTEMD_SERVICE,
172ee7f6428SMatt Spinler                                        SYSTEMD_OBJ_PATH,
173ee7f6428SMatt Spinler                                        SYSTEMD_INTERFACE,
174ee7f6428SMatt Spinler                                        "StartUnit");
175ee7f6428SMatt Spinler 
176ee7f6428SMatt Spinler     method.append(FAN_CONTROL_READY_TARGET);
177ee7f6428SMatt Spinler     method.append("replace");
178ee7f6428SMatt Spinler 
179ee7f6428SMatt Spinler     auto response = _bus.call(method);
180ee7f6428SMatt Spinler     if (response.is_method_error())
181ee7f6428SMatt Spinler     {
182ee7f6428SMatt Spinler         //TODO openbmc/openbmc#1555 create an elog
183ee7f6428SMatt Spinler         log<level::ERR>("Failed to start fan control ready target");
184ee7f6428SMatt Spinler         throw std::runtime_error("Failed to start fan control ready target");
185ee7f6428SMatt Spinler     }
186ee7f6428SMatt Spinler }
187e10416ecSMatt Spinler 
188*f96b01e2SGunnar Mills } // namespace control
189*f96b01e2SGunnar Mills } // namespace fan
190*f96b01e2SGunnar Mills } // namespace phosphor
191