blob: 14bd9d2d90bbd891460b1f78d7ea640d85f13676 [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 */
Matthew Barthdf3e8d62017-05-31 11:07:24 -050016#include <phosphor-logging/elog.hpp>
Matt Spinler7f88fe62017-04-10 14:39:02 -050017#include "zone.hpp"
Matthew Barthdf3e8d62017-05-31 11:07:24 -050018#include "utility.hpp"
Matt Spinler7f88fe62017-04-10 14:39:02 -050019
20namespace phosphor
21{
22namespace fan
23{
24namespace control
25{
26
Matthew Barthdf3e8d62017-05-31 11:07:24 -050027using namespace phosphor::logging;
Matt Spinler7f88fe62017-04-10 14:39:02 -050028
Matthew Barth14184132017-05-19 14:37:30 -050029Zone::Zone(Mode mode,
30 sdbusplus::bus::bus& bus,
Matt Spinler7f88fe62017-04-10 14:39:02 -050031 const ZoneDefinition& def) :
32 _bus(bus),
33 _fullSpeed(std::get<fullSpeedPos>(def)),
Matthew Barth1de66622017-06-12 13:13:02 -050034 _zoneNum(std::get<zoneNumPos>(def)),
35 _defFloorSpeed(std::get<floorSpeedPos>(def))
Matt Spinler7f88fe62017-04-10 14:39:02 -050036{
37 auto& fanDefs = std::get<fanListPos>(def);
38
39 for (auto& def : fanDefs)
40 {
41 _fans.emplace_back(std::make_unique<Fan>(bus, def));
42 }
Matthew Barth38a93a82017-05-11 14:12:27 -050043
Matthew Barth14184132017-05-19 14:37:30 -050044 // Do not enable set speed events when in init mode
45 if (mode != Mode::init)
Matthew Barth17d1fe22017-05-11 15:00:36 -050046 {
Matthew Barth14184132017-05-19 14:37:30 -050047 // Setup signal trigger for set speed events
48 for (auto& event : std::get<setSpeedEventsPos>(def))
Matthew Barth17d1fe22017-05-11 15:00:36 -050049 {
Matthew Barthdf3e8d62017-05-31 11:07:24 -050050 // Get the current value for each property
51 for (auto& entry : std::get<groupPos>(event))
52 {
53 try
54 {
Matthew Barth9e741ed2017-06-02 16:29:09 -050055 PropertyVariantType property;
Matthew Barthdf3e8d62017-05-31 11:07:24 -050056 getProperty(_bus,
57 entry.first,
58 std::get<intfPos>(entry.second),
59 std::get<propPos>(entry.second),
Matthew Barth9e741ed2017-06-02 16:29:09 -050060 property);
Matthew Barthdf3e8d62017-05-31 11:07:24 -050061 setPropertyValue(entry.first.c_str(),
Matthew Barthcec5ab72017-06-02 15:20:56 -050062 std::get<intfPos>(entry.second).c_str(),
Matthew Barthdf3e8d62017-05-31 11:07:24 -050063 std::get<propPos>(entry.second).c_str(),
Matthew Barth9e741ed2017-06-02 16:29:09 -050064 property);
Matthew Barthdf3e8d62017-05-31 11:07:24 -050065 }
66 catch (const std::exception& e)
67 {
68 log<level::ERR>(e.what());
69 }
70 }
71 // Setup signal matches for property change events
Matthew Barth14184132017-05-19 14:37:30 -050072 for (auto& prop : std::get<propChangeListPos>(event))
73 {
74 _signalEvents.emplace_back(
Matthew Barth34f1bda2017-05-31 13:45:36 -050075 std::make_unique<EventData>(
Matthew Barth14184132017-05-19 14:37:30 -050076 EventData
77 {
78 std::get<groupPos>(event),
79 std::get<handlerObjPos>(prop),
80 std::get<actionPos>(event)
81 }));
82 _matches.emplace_back(
83 bus,
84 std::get<signaturePos>(prop).c_str(),
Matthew Barth34f1bda2017-05-31 13:45:36 -050085 std::bind(std::mem_fn(&Zone::handleEvent),
86 this,
87 std::placeholders::_1,
88 _signalEvents.back().get()));
Matthew Barth14184132017-05-19 14:37:30 -050089 }
Matthew Barthdf3e8d62017-05-31 11:07:24 -050090 // Run action function for initial event state
91 std::get<actionPos>(event)(*this,
92 std::get<groupPos>(event));
Matthew Barth17d1fe22017-05-11 15:00:36 -050093 }
Matthew Barth38a93a82017-05-11 14:12:27 -050094 }
Matt Spinler7f88fe62017-04-10 14:39:02 -050095}
96
97
98void Zone::setSpeed(uint64_t speed)
99{
100 for (auto& fan : _fans)
101 {
Matthew Barth4af419c2017-06-12 13:39:31 -0500102 //TODO openbmc/openbmc#1626 Move to control algorithm function
103 if (speed < _floorSpeed)
104 {
105 speed = _floorSpeed;
106 }
Matt Spinler7f88fe62017-04-10 14:39:02 -0500107 fan->setSpeed(speed);
108 }
109}
110
Matthew Barth861d77c2017-05-22 14:18:25 -0500111void Zone::setActiveAllow(const Group* group, bool isActiveAllow)
112{
113 _active[group] = isActiveAllow;
114 if (!isActiveAllow)
115 {
116 _isActive = false;
117 }
118 else
119 {
120 // Check all entries are set to allow control active
121 auto actPred = [](auto const& entry) {return entry.second;};
122 _isActive = std::all_of(_active.begin(),
123 _active.end(),
124 actPred);
125 }
126}
127
Matthew Barthdf3e8d62017-05-31 11:07:24 -0500128void Zone::getProperty(sdbusplus::bus::bus& bus,
129 const std::string& path,
130 const std::string& iface,
131 const std::string& prop,
Matthew Barth9e741ed2017-06-02 16:29:09 -0500132 PropertyVariantType& value)
Matthew Barthdf3e8d62017-05-31 11:07:24 -0500133{
Matthew Barthdf3e8d62017-05-31 11:07:24 -0500134 auto serv = phosphor::fan::util::getService(path, iface, bus);
135 auto hostCall = bus.new_method_call(serv.c_str(),
136 path.c_str(),
137 "org.freedesktop.DBus.Properties",
138 "Get");
139 hostCall.append(iface);
140 hostCall.append(prop);
141 auto hostResponseMsg = bus.call(hostCall);
142 if (hostResponseMsg.is_method_error())
143 {
144 throw std::runtime_error(
145 "Error in host call response for retrieving property");
146 }
Matthew Barth9e741ed2017-06-02 16:29:09 -0500147 hostResponseMsg.read(value);
Matthew Barthdf3e8d62017-05-31 11:07:24 -0500148}
149
Matthew Barth38a93a82017-05-11 14:12:27 -0500150void Zone::handleEvent(sdbusplus::message::message& msg,
Matthew Barth34f1bda2017-05-31 13:45:36 -0500151 const EventData* eventData)
Matthew Barth38a93a82017-05-11 14:12:27 -0500152{
153 // Handle the callback
Matthew Barth34f1bda2017-05-31 13:45:36 -0500154 std::get<eventHandlerPos>(*eventData)(_bus, msg, *this);
Matthew Barth17d1fe22017-05-11 15:00:36 -0500155 // Perform the action
Matthew Barth34f1bda2017-05-31 13:45:36 -0500156 std::get<eventActionPos>(*eventData)(*this,
157 std::get<eventGroupPos>(*eventData));
Matthew Barth38a93a82017-05-11 14:12:27 -0500158}
159
Matt Spinler7f88fe62017-04-10 14:39:02 -0500160}
161}
162}