blob: f618c105b7ca621df87a68ec801680a82b59de1b [file] [log] [blame]
Matt Spinler7f88fe62017-04-10 14:39:02 -05001#pragma once
Matthew Bartha9561842017-06-29 11:43:45 -05002#include <chrono>
Matt Spinler7f88fe62017-04-10 14:39:02 -05003#include <vector>
Matthew Barthe0ca13e2017-06-13 16:29:09 -05004#include <algorithm>
Matt Spinler7f88fe62017-04-10 14:39:02 -05005#include <sdbusplus/bus.hpp>
Matthew Barth38a93a82017-05-11 14:12:27 -05006#include <sdbusplus/server.hpp>
Matt Spinler7f88fe62017-04-10 14:39:02 -05007#include "fan.hpp"
8#include "types.hpp"
Matthew Barth8600d9a2017-06-23 14:38:05 -05009#include "timer.hpp"
Matt Spinler7f88fe62017-04-10 14:39:02 -050010
11namespace phosphor
12{
13namespace fan
14{
15namespace control
16{
17
18/**
Matthew Barth14184132017-05-19 14:37:30 -050019 * The mode fan control will run in:
20 * - init - only do the initialization steps
21 * - control - run normal control algorithms
22 */
23enum class Mode
24{
25 init,
26 control
27};
28
29/**
Matt Spinler7f88fe62017-04-10 14:39:02 -050030 * @class Represents a fan control zone, which is a group of fans
31 * that behave the same.
32 */
33class Zone
34{
35 public:
36
37 Zone() = delete;
38 Zone(const Zone&) = delete;
39 Zone(Zone&&) = default;
40 Zone& operator=(const Zone&) = delete;
41 Zone& operator=(Zone&&) = delete;
42 ~Zone() = default;
43
44 /**
45 * Constructor
46 * Creates the appropriate fan objects based on
47 * the zone definition data passed in.
48 *
Matthew Barth14184132017-05-19 14:37:30 -050049 * @param[in] mode - mode of fan control
Matt Spinler7f88fe62017-04-10 14:39:02 -050050 * @param[in] bus - the dbus object
Matthew Barth8600d9a2017-06-23 14:38:05 -050051 * @param[in] events - sd_event pointer
Matt Spinler7f88fe62017-04-10 14:39:02 -050052 * @param[in] def - the fan zone definition data
53 */
Matthew Barth14184132017-05-19 14:37:30 -050054 Zone(Mode mode,
55 sdbusplus::bus::bus& bus,
Matthew Barth8600d9a2017-06-23 14:38:05 -050056 phosphor::fan::event::EventPtr& events,
Matt Spinler7f88fe62017-04-10 14:39:02 -050057 const ZoneDefinition& def);
58
59 /**
60 * Sets all fans in the zone to the speed
61 * passed in
62 *
63 * @param[in] speed - the fan speed
64 */
65 void setSpeed(uint64_t speed);
66
67 /**
68 * Sets the zone to full speed
69 */
70 inline void setFullSpeed()
71 {
72 if (_fullSpeed != 0)
73 {
74 setSpeed(_fullSpeed);
75 }
76 }
77
Matthew Barth38a93a82017-05-11 14:12:27 -050078 /**
Matthew Barth861d77c2017-05-22 14:18:25 -050079 * @brief Sets the automatic fan control allowed active state
80 *
81 * @param[in] group - A group that affects the active state
82 * @param[in] isActiveAllow - Active state according to group
83 */
84 void setActiveAllow(const Group* group, bool isActiveAllow);
85
86 /**
Matthew Barth38a93a82017-05-11 14:12:27 -050087 * @brief Sets a given object's property value
88 *
89 * @param[in] object - Name of the object containing the property
Matthew Barthcec5ab72017-06-02 15:20:56 -050090 * @param[in] interface - Interface name containing the property
Matthew Barth38a93a82017-05-11 14:12:27 -050091 * @param[in] property - Property name
92 * @param[in] value - Property value
93 */
Matthew Barth9e741ed2017-06-02 16:29:09 -050094 template <typename T>
Matthew Barth38a93a82017-05-11 14:12:27 -050095 void setPropertyValue(const char* object,
Matthew Barthcec5ab72017-06-02 15:20:56 -050096 const char* interface,
Matthew Barth38a93a82017-05-11 14:12:27 -050097 const char* property,
Matthew Barth9e741ed2017-06-02 16:29:09 -050098 T value)
Matthew Barth38a93a82017-05-11 14:12:27 -050099 {
Matthew Barthcec5ab72017-06-02 15:20:56 -0500100 _properties[object][interface][property] = value;
Matthew Barth38a93a82017-05-11 14:12:27 -0500101 };
102
Matthew Barth17d1fe22017-05-11 15:00:36 -0500103 /**
104 * @brief Get the value of an object's property
105 *
106 * @param[in] object - Name of the object containing the property
Matthew Barthcec5ab72017-06-02 15:20:56 -0500107 * @param[in] interface - Interface name containing the property
Matthew Barth17d1fe22017-05-11 15:00:36 -0500108 * @param[in] property - Property name
109 *
110 * @return - The property value
111 */
Matthew Barth9e741ed2017-06-02 16:29:09 -0500112 template <typename T>
Matthew Barth17d1fe22017-05-11 15:00:36 -0500113 inline auto getPropertyValue(const std::string& object,
Matthew Barthcec5ab72017-06-02 15:20:56 -0500114 const std::string& interface,
Matthew Barth17d1fe22017-05-11 15:00:36 -0500115 const std::string& property)
116 {
Matthew Barth9e741ed2017-06-02 16:29:09 -0500117 return sdbusplus::message::variant_ns::get<T>(
118 _properties[object][interface][property]);
Matthew Barth17d1fe22017-05-11 15:00:36 -0500119 };
120
Matthew Barth1de66622017-06-12 13:13:02 -0500121 /**
Matthew Barth604329e2017-08-04 11:18:28 -0500122 * @brief Get the object's property variant
123 *
124 * @param[in] object - Name of the object containing the property
125 * @param[in] interface - Interface name containing the property
126 * @param[in] property - Property name
127 *
128 * @return - The property variant
129 */
130 inline auto getPropValueVariant(const std::string& object,
131 const std::string& interface,
132 const std::string& property)
133 {
134 return _properties.at(object).at(interface).at(property);
135 };
136
137 /**
138 * @brief Initialize a set speed event properties and actions
139 *
140 * @param[in] event - Set speed event
141 */
142 void initEvent(const SetSpeedEvent& event);
143
144 /**
Matthew Barth1de66622017-06-12 13:13:02 -0500145 * @brief Get the default floor speed
146 *
147 * @return - The defined default floor speed
148 */
149 inline auto getDefFloor()
150 {
151 return _defFloorSpeed;
152 };
153
Matthew Barth4af419c2017-06-12 13:39:31 -0500154 /**
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500155 * @brief Get the ceiling speed
156 *
157 * @return - The current ceiling speed
158 */
159 inline auto& getCeiling() const
160 {
161 return _ceilingSpeed;
162 };
163
164 /**
165 * @brief Set the ceiling speed to the given speed
166 *
167 * @param[in] speed - Speed to set the ceiling to
168 */
169 inline void setCeiling(uint64_t speed)
170 {
171 _ceilingSpeed = speed;
172 };
173
174 /**
175 * @brief Swaps the ceiling key value with what's given and
176 * returns the value that was swapped.
177 *
178 * @param[in] keyValue - New ceiling key value
179 *
180 * @return - Ceiling key value prior to swapping
181 */
182 inline auto swapCeilingKeyValue(int64_t keyValue)
183 {
184 std::swap(_ceilingKeyValue, keyValue);
185 return keyValue;
186 };
187
Matthew Barth24623522017-06-21 14:09:57 -0500188 /**
189 * @brief Get the increase speed delta
190 *
191 * @return - The current increase speed delta
192 */
193 inline auto& getIncSpeedDelta() const
194 {
195 return _incSpeedDelta;
196 };
197
Matthew Barth240397b2017-06-22 11:23:30 -0500198 /**
Matthew Barth0ce99d82017-06-22 15:07:29 -0500199 * @brief Get the decrease speed delta
200 *
201 * @return - The current decrease speed delta
202 */
203 inline auto& getDecSpeedDelta() const
204 {
205 return _decSpeedDelta;
206 };
207
208 /**
Matthew Barthb4a7cb92017-06-28 15:29:50 -0500209 * @brief Set the floor speed to the given speed and increase target
210 * speed to the floor when target is below floor.
211 *
212 * @param[in] speed - Speed to set the floor to
213 */
214 void setFloor(uint64_t speed);
215
216 /**
Matthew Barth240397b2017-06-22 11:23:30 -0500217 * @brief Calculate the requested target speed from the given delta
218 * and increase the fan speeds, not going above the ceiling.
219 *
220 * @param[in] targetDelta - The delta to increase the target speed by
221 */
222 void requestSpeedIncrease(uint64_t targetDelta);
223
Matthew Barth0ce99d82017-06-22 15:07:29 -0500224 /**
225 * @brief Calculate the requested target speed from the given delta
226 * and increase the fan speeds, not going above the ceiling.
227 *
228 * @param[in] targetDelta - The delta to increase the target speed by
229 */
230 void requestSpeedDecrease(uint64_t targetDelta);
231
Matthew Barth8600d9a2017-06-23 14:38:05 -0500232 /**
Matthew Barth1ee48f22017-06-27 15:14:48 -0500233 * @brief Callback function for the increase timer that delays
234 * processing of requested speed increases while fans are increasing
235 */
236 void incTimerExpired();
237
238 /**
Matthew Barth8600d9a2017-06-23 14:38:05 -0500239 * @brief Callback function for the decrease timer that processes any
240 * requested speed decreases if allowed
241 */
242 void decTimerExpired();
243
Matt Spinler7f88fe62017-04-10 14:39:02 -0500244 private:
245
246 /**
247 * The dbus object
248 */
249 sdbusplus::bus::bus& _bus;
250
251 /**
252 * Full speed for the zone
253 */
254 const uint64_t _fullSpeed;
255
256 /**
257 * The zone number
258 */
259 const size_t _zoneNum;
260
261 /**
Matthew Barth1de66622017-06-12 13:13:02 -0500262 * The default floor speed for the zone
263 */
264 const uint64_t _defFloorSpeed;
265
266 /**
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500267 * The default ceiling speed for the zone
268 */
269 const uint64_t _defCeilingSpeed;
270
271 /**
Matthew Barth4af419c2017-06-12 13:39:31 -0500272 * The floor speed to not go below
273 */
274 uint64_t _floorSpeed = _defFloorSpeed;
275
276 /**
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500277 * The ceiling speed to not go above
278 */
279 uint64_t _ceilingSpeed = _defCeilingSpeed;
280
281 /**
282 * The previous sensor value for calculating the ceiling
283 */
284 int64_t _ceilingKeyValue = 0;
285
286 /**
Matthew Barth861d77c2017-05-22 14:18:25 -0500287 * Automatic fan control active state
288 */
289 bool _isActive = true;
290
291 /**
Matthew Barth240397b2017-06-22 11:23:30 -0500292 * Target speed for this zone
293 */
294 uint64_t _targetSpeed = _fullSpeed;
295
296 /**
Matthew Barth24623522017-06-21 14:09:57 -0500297 * Speed increase delta
298 */
299 uint64_t _incSpeedDelta = 0;
300
301 /**
Matthew Barth0ce99d82017-06-22 15:07:29 -0500302 * Speed decrease delta
303 */
304 uint64_t _decSpeedDelta = 0;
305
306 /**
Matthew Bartha9561842017-06-29 11:43:45 -0500307 * Speed increase delay in seconds
308 */
309 std::chrono::seconds _incDelay;
310
311 /**
312 * Speed decrease interval in seconds
313 */
314 std::chrono::seconds _decInterval;
315
316 /**
Matthew Barth1ee48f22017-06-27 15:14:48 -0500317 * The increase timer object
318 */
319 phosphor::fan::util::Timer _incTimer;
320
321 /**
Matthew Barth8600d9a2017-06-23 14:38:05 -0500322 * The decrease timer object
323 */
324 phosphor::fan::util::Timer _decTimer;
325
326 /**
Matt Spinler7f88fe62017-04-10 14:39:02 -0500327 * The vector of fans in this zone
328 */
329 std::vector<std::unique_ptr<Fan>> _fans;
Matthew Barth38a93a82017-05-11 14:12:27 -0500330
331 /**
332 * @brief Map of object property values
333 */
Matthew Barthcec5ab72017-06-02 15:20:56 -0500334 std::map<std::string,
335 std::map<std::string,
336 std::map<std::string,
Matthew Barth9e741ed2017-06-02 16:29:09 -0500337 PropertyVariantType>>> _properties;
Matthew Barth38a93a82017-05-11 14:12:27 -0500338
339 /**
Matthew Barth861d77c2017-05-22 14:18:25 -0500340 * @brief Map of active fan control allowed by groups
341 */
342 std::map<const Group*, bool> _active;
343
344 /**
Matthew Barth38a93a82017-05-11 14:12:27 -0500345 * @brief List of signal event arguments
346 */
Matthew Barth34f1bda2017-05-31 13:45:36 -0500347 std::vector<std::unique_ptr<EventData>> _signalEvents;
Matthew Barth38a93a82017-05-11 14:12:27 -0500348
349 /**
350 * @brief list of Dbus matches for callbacks
351 */
352 std::vector<sdbusplus::server::match::match> _matches;
353
354 /**
Matthew Barth1bf0ce42017-06-23 16:16:30 -0500355 * @brief Refresh the given property's cached value
356 *
357 * @param[in] bus - the bus to use
358 * @param[in] path - the dbus path name
359 * @param[in] iface - the dbus interface name
360 * @param[in] prop - the property name
361 */
362 void refreshProperty(sdbusplus::bus::bus& bus,
363 const std::string& path,
364 const std::string& iface,
365 const std::string& prop);
366
367 /**
Matthew Barthdf3e8d62017-05-31 11:07:24 -0500368 * @brief Get a property value from the path/interface given
369 *
370 * @param[in] bus - the bus to use
371 * @param[in] path - the dbus path name
372 * @param[in] iface - the dbus interface name
373 * @param[in] prop - the property name
374 * @param[out] value - the value of the property
375 */
Matthew Barthdf3e8d62017-05-31 11:07:24 -0500376 static void getProperty(sdbusplus::bus::bus& bus,
377 const std::string& path,
378 const std::string& iface,
379 const std::string& prop,
Matthew Barth9e741ed2017-06-02 16:29:09 -0500380 PropertyVariantType& value);
Matthew Barthdf3e8d62017-05-31 11:07:24 -0500381
382 /**
Matthew Barth34f1bda2017-05-31 13:45:36 -0500383 * @brief Dbus signal change callback handler
Matthew Barth38a93a82017-05-11 14:12:27 -0500384 *
Matthew Barth34f1bda2017-05-31 13:45:36 -0500385 * @param[in] msg - Expanded sdbusplus message data
386 * @param[in] eventData - The single event's data
Matthew Barth38a93a82017-05-11 14:12:27 -0500387 */
Matthew Barth34f1bda2017-05-31 13:45:36 -0500388 void handleEvent(sdbusplus::message::message& msg,
389 const EventData* eventData);
Matt Spinler7f88fe62017-04-10 14:39:02 -0500390};
391
392}
393}
394}