blob: 5ed0c3a77ed682608107d7f0183951253bbbd701 [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 }
Matt Spinler7f88fe62017-04-10 14:39:02 -0500113 fan->setSpeed(speed);
114 }
115}
116
Matthew Barth861d77c2017-05-22 14:18:25 -0500117void Zone::setActiveAllow(const Group* group, bool isActiveAllow)
118{
119 _active[group] = isActiveAllow;
120 if (!isActiveAllow)
121 {
122 _isActive = false;
123 }
124 else
125 {
126 // Check all entries are set to allow control active
127 auto actPred = [](auto const& entry) {return entry.second;};
128 _isActive = std::all_of(_active.begin(),
129 _active.end(),
130 actPred);
131 }
132}
133
Matthew Barth240397b2017-06-22 11:23:30 -0500134void Zone::requestSpeedIncrease(uint64_t targetDelta)
135{
136 // Only increase speed when delta is higher than
137 // the current increase delta for the zone and currently under ceiling
138 if (targetDelta > _incSpeedDelta &&
139 _targetSpeed < _ceilingSpeed)
140 {
141 _targetSpeed = (targetDelta - _incSpeedDelta) + _targetSpeed;
142 _incSpeedDelta = targetDelta;
143 //TODO openbmc/openbmc#1625 Cancel current timer countdown
144 //TODO Floor speed above target, update target to floor speed
145 if (_targetSpeed < _floorSpeed)
146 {
147 _targetSpeed = _floorSpeed;
148 }
149 // Target speed can not go above a defined ceiling speed
150 if (_targetSpeed > _ceilingSpeed)
151 {
152 _targetSpeed = _ceilingSpeed;
153 }
154
155 setSpeed(_targetSpeed);
156 //TODO openbmc/openbmc#1625 Start timer countdown for fan speed increase
157 }
158 //TODO openbmc/openbmc#1625 Clear increase delta when timer expires
159 _incSpeedDelta = 0;
160}
161
Matthew Barthdf3e8d62017-05-31 11:07:24 -0500162void Zone::getProperty(sdbusplus::bus::bus& bus,
163 const std::string& path,
164 const std::string& iface,
165 const std::string& prop,
Matthew Barth9e741ed2017-06-02 16:29:09 -0500166 PropertyVariantType& value)
Matthew Barthdf3e8d62017-05-31 11:07:24 -0500167{
Matthew Barthdf3e8d62017-05-31 11:07:24 -0500168 auto serv = phosphor::fan::util::getService(path, iface, bus);
169 auto hostCall = bus.new_method_call(serv.c_str(),
170 path.c_str(),
171 "org.freedesktop.DBus.Properties",
172 "Get");
173 hostCall.append(iface);
174 hostCall.append(prop);
175 auto hostResponseMsg = bus.call(hostCall);
176 if (hostResponseMsg.is_method_error())
177 {
Dinesh Chinari618027a2017-06-26 23:26:50 -0500178 log<level::ERR>("Error in host call response for retrieving property");
179 elog<InternalFailure>();
Matthew Barthdf3e8d62017-05-31 11:07:24 -0500180 }
Matthew Barth9e741ed2017-06-02 16:29:09 -0500181 hostResponseMsg.read(value);
Matthew Barthdf3e8d62017-05-31 11:07:24 -0500182}
183
Matthew Barth38a93a82017-05-11 14:12:27 -0500184void Zone::handleEvent(sdbusplus::message::message& msg,
Matthew Barth34f1bda2017-05-31 13:45:36 -0500185 const EventData* eventData)
Matthew Barth38a93a82017-05-11 14:12:27 -0500186{
187 // Handle the callback
Matthew Barth34f1bda2017-05-31 13:45:36 -0500188 std::get<eventHandlerPos>(*eventData)(_bus, msg, *this);
Matthew Barth17d1fe22017-05-11 15:00:36 -0500189 // Perform the action
Matthew Barth34f1bda2017-05-31 13:45:36 -0500190 std::get<eventActionPos>(*eventData)(*this,
191 std::get<eventGroupPos>(*eventData));
Matthew Barth38a93a82017-05-11 14:12:27 -0500192}
193
Matt Spinler7f88fe62017-04-10 14:39:02 -0500194}
195}
196}