blob: d569aa8a9d3bc20b87afb8337413e77b5b9d9ea0 [file] [log] [blame]
Matt Spinler7f88fe62017-04-10 14:39:02 -05001/**
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 */
Dinesh Chinari618027a2017-06-26 23:26:50 -050016#include <phosphor-logging/log.hpp>
Matthew Barthdf3e8d62017-05-31 11:07:24 -050017#include <phosphor-logging/elog.hpp>
Dinesh Chinari618027a2017-06-26 23:26:50 -050018#include <phosphor-logging/elog-errors.hpp>
19#include <xyz/openbmc_project/Common/error.hpp>
Matt Spinler7f88fe62017-04-10 14:39:02 -050020#include "zone.hpp"
Matthew Barthdf3e8d62017-05-31 11:07:24 -050021#include "utility.hpp"
Matt Spinler7f88fe62017-04-10 14:39:02 -050022
23namespace phosphor
24{
25namespace fan
26{
27namespace control
28{
29
Matthew Barthdf3e8d62017-05-31 11:07:24 -050030using namespace phosphor::logging;
Dinesh Chinari618027a2017-06-26 23:26:50 -050031using InternalFailure = sdbusplus::xyz::openbmc_project::Common::
32 Error::InternalFailure;
Matt Spinler7f88fe62017-04-10 14:39:02 -050033
Matthew Barth14184132017-05-19 14:37:30 -050034Zone::Zone(Mode mode,
35 sdbusplus::bus::bus& bus,
Matt Spinler7f88fe62017-04-10 14:39:02 -050036 const ZoneDefinition& def) :
37 _bus(bus),
38 _fullSpeed(std::get<fullSpeedPos>(def)),
Matthew Barth1de66622017-06-12 13:13:02 -050039 _zoneNum(std::get<zoneNumPos>(def)),
Matthew Barthe0ca13e2017-06-13 16:29:09 -050040 _defFloorSpeed(std::get<floorSpeedPos>(def)),
41 _defCeilingSpeed(std::get<fullSpeedPos>(def))
Matt Spinler7f88fe62017-04-10 14:39:02 -050042{
43 auto& fanDefs = std::get<fanListPos>(def);
44
45 for (auto& def : fanDefs)
46 {
47 _fans.emplace_back(std::make_unique<Fan>(bus, def));
48 }
Matthew Barth38a93a82017-05-11 14:12:27 -050049
Matthew Barth14184132017-05-19 14:37:30 -050050 // Do not enable set speed events when in init mode
51 if (mode != Mode::init)
Matthew Barth17d1fe22017-05-11 15:00:36 -050052 {
Matthew Barth14184132017-05-19 14:37:30 -050053 // Setup signal trigger for set speed events
54 for (auto& event : std::get<setSpeedEventsPos>(def))
Matthew Barth17d1fe22017-05-11 15:00:36 -050055 {
Matthew Barthdf3e8d62017-05-31 11:07:24 -050056 // Get the current value for each property
57 for (auto& entry : std::get<groupPos>(event))
58 {
59 try
60 {
Matthew Barth9e741ed2017-06-02 16:29:09 -050061 PropertyVariantType property;
Matthew Barthdf3e8d62017-05-31 11:07:24 -050062 getProperty(_bus,
63 entry.first,
64 std::get<intfPos>(entry.second),
65 std::get<propPos>(entry.second),
Matthew Barth9e741ed2017-06-02 16:29:09 -050066 property);
Matthew Barthdf3e8d62017-05-31 11:07:24 -050067 setPropertyValue(entry.first.c_str(),
Matthew Barthcec5ab72017-06-02 15:20:56 -050068 std::get<intfPos>(entry.second).c_str(),
Matthew Barthdf3e8d62017-05-31 11:07:24 -050069 std::get<propPos>(entry.second).c_str(),
Matthew Barth9e741ed2017-06-02 16:29:09 -050070 property);
Matthew Barthdf3e8d62017-05-31 11:07:24 -050071 }
72 catch (const std::exception& e)
73 {
74 log<level::ERR>(e.what());
75 }
76 }
77 // Setup signal matches for property change events
Matthew Barth14184132017-05-19 14:37:30 -050078 for (auto& prop : std::get<propChangeListPos>(event))
79 {
80 _signalEvents.emplace_back(
Matthew Barth34f1bda2017-05-31 13:45:36 -050081 std::make_unique<EventData>(
Matthew Barth14184132017-05-19 14:37:30 -050082 EventData
83 {
84 std::get<groupPos>(event),
85 std::get<handlerObjPos>(prop),
86 std::get<actionPos>(event)
87 }));
88 _matches.emplace_back(
89 bus,
90 std::get<signaturePos>(prop).c_str(),
Matthew Barth34f1bda2017-05-31 13:45:36 -050091 std::bind(std::mem_fn(&Zone::handleEvent),
92 this,
93 std::placeholders::_1,
94 _signalEvents.back().get()));
Matthew Barth14184132017-05-19 14:37:30 -050095 }
Matthew Barthdf3e8d62017-05-31 11:07:24 -050096 // Run action function for initial event state
97 std::get<actionPos>(event)(*this,
98 std::get<groupPos>(event));
Matthew Barth17d1fe22017-05-11 15:00:36 -050099 }
Matthew Barth38a93a82017-05-11 14:12:27 -0500100 }
Matt Spinler7f88fe62017-04-10 14:39:02 -0500101}
102
103
104void Zone::setSpeed(uint64_t speed)
105{
106 for (auto& fan : _fans)
107 {
Matthew Barth4af419c2017-06-12 13:39:31 -0500108 //TODO openbmc/openbmc#1626 Move to control algorithm function
109 if (speed < _floorSpeed)
110 {
111 speed = _floorSpeed;
112 }
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500113 //TODO openbmc/openbmc#1626 Move to control algorithm function
114 if (speed > _ceilingSpeed)
115 {
116 speed = _ceilingSpeed;
117 }
Matt Spinler7f88fe62017-04-10 14:39:02 -0500118 fan->setSpeed(speed);
119 }
120}
121
Matthew Barth861d77c2017-05-22 14:18:25 -0500122void Zone::setActiveAllow(const Group* group, bool isActiveAllow)
123{
124 _active[group] = isActiveAllow;
125 if (!isActiveAllow)
126 {
127 _isActive = false;
128 }
129 else
130 {
131 // Check all entries are set to allow control active
132 auto actPred = [](auto const& entry) {return entry.second;};
133 _isActive = std::all_of(_active.begin(),
134 _active.end(),
135 actPred);
136 }
137}
138
Matthew Barthdf3e8d62017-05-31 11:07:24 -0500139void Zone::getProperty(sdbusplus::bus::bus& bus,
140 const std::string& path,
141 const std::string& iface,
142 const std::string& prop,
Matthew Barth9e741ed2017-06-02 16:29:09 -0500143 PropertyVariantType& value)
Matthew Barthdf3e8d62017-05-31 11:07:24 -0500144{
Matthew Barthdf3e8d62017-05-31 11:07:24 -0500145 auto serv = phosphor::fan::util::getService(path, iface, bus);
146 auto hostCall = bus.new_method_call(serv.c_str(),
147 path.c_str(),
148 "org.freedesktop.DBus.Properties",
149 "Get");
150 hostCall.append(iface);
151 hostCall.append(prop);
152 auto hostResponseMsg = bus.call(hostCall);
153 if (hostResponseMsg.is_method_error())
154 {
Dinesh Chinari618027a2017-06-26 23:26:50 -0500155 log<level::ERR>("Error in host call response for retrieving property");
156 elog<InternalFailure>();
Matthew Barthdf3e8d62017-05-31 11:07:24 -0500157 }
Matthew Barth9e741ed2017-06-02 16:29:09 -0500158 hostResponseMsg.read(value);
Matthew Barthdf3e8d62017-05-31 11:07:24 -0500159}
160
Matthew Barth38a93a82017-05-11 14:12:27 -0500161void Zone::handleEvent(sdbusplus::message::message& msg,
Matthew Barth34f1bda2017-05-31 13:45:36 -0500162 const EventData* eventData)
Matthew Barth38a93a82017-05-11 14:12:27 -0500163{
164 // Handle the callback
Matthew Barth34f1bda2017-05-31 13:45:36 -0500165 std::get<eventHandlerPos>(*eventData)(_bus, msg, *this);
Matthew Barth17d1fe22017-05-11 15:00:36 -0500166 // Perform the action
Matthew Barth34f1bda2017-05-31 13:45:36 -0500167 std::get<eventActionPos>(*eventData)(*this,
168 std::get<eventGroupPos>(*eventData));
Matthew Barth38a93a82017-05-11 14:12:27 -0500169}
170
Matt Spinler7f88fe62017-04-10 14:39:02 -0500171}
172}
173}