blob: 5256018ed4552d7e65a597a1cb057142b4adc053 [file] [log] [blame]
Matthew Barth4f0d3b72020-08-27 14:32:15 -05001/**
2 * Copyright © 2020 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 */
16#pragma once
17
18#include "config_base.hpp"
Matthew Barthde90fb42021-03-04 16:34:28 -060019#include "fan.hpp"
Matthew Bartha0dd1352021-03-09 11:10:49 -060020#include "xyz/openbmc_project/Control/ThermalMode/server.hpp"
Matthew Barth4f0d3b72020-08-27 14:32:15 -050021
22#include <nlohmann/json.hpp>
Matthew Barthacd737c2021-03-04 11:04:01 -060023#include <sdbusplus/bus.hpp>
Matthew Barth603ef162021-03-24 15:34:53 -050024#include <sdeventplus/event.hpp>
Matthew Barth4f0d3b72020-08-27 14:32:15 -050025
Matthew Barth651f03a2020-08-27 16:15:11 -050026#include <any>
27#include <functional>
28#include <map>
29#include <tuple>
30
Matthew Barth4f0d3b72020-08-27 14:32:15 -050031namespace phosphor::fan::control::json
32{
33
Matthew Barth603ef162021-03-24 15:34:53 -050034class Manager;
35
Matthew Barth4f0d3b72020-08-27 14:32:15 -050036using json = nlohmann::json;
37
Matthew Bartha0dd1352021-03-09 11:10:49 -060038/* Extend the Control::ThermalMode interface */
39using ThermalObject = sdbusplus::server::object::object<
40 sdbusplus::xyz::openbmc_project::Control::server::ThermalMode>;
41
Matthew Barth4f0d3b72020-08-27 14:32:15 -050042/**
43 * @class Zone - Represents a configured fan control zone
44 *
45 * A zone object contains the configured attributes for a zone that groups
Matthew Barthe47c9582021-03-09 14:24:02 -060046 * a number of fans together to be under the same target control. These
47 * configuration attributes include, but are not limited to, the default ceiling
48 * of the fans within the zone, a default floor, the delay between increases, a
49 * decrease interval, and any profiles(OPTIONAL) the zone should be included in.
Matthew Barth4f0d3b72020-08-27 14:32:15 -050050 *
51 * (When no profile for a zone is given, the zone defaults to always exist)
52 *
53 */
Matthew Bartha0dd1352021-03-09 11:10:49 -060054class Zone : public ConfigBase, public ThermalObject
Matthew Barth4f0d3b72020-08-27 14:32:15 -050055{
56 public:
57 /* JSON file name for zones */
58 static constexpr auto confFileName = "zones.json";
Matthew Barth216229c2020-09-24 13:47:33 -050059 static constexpr auto thermModeIntf =
60 "xyz.openbmc_project.Control.ThermalMode";
61 static constexpr auto supportedProp = "Supported";
62 static constexpr auto currentProp = "Current";
Matthew Barth651f03a2020-08-27 16:15:11 -050063
Matthew Barth4f0d3b72020-08-27 14:32:15 -050064 Zone() = delete;
65 Zone(const Zone&) = delete;
66 Zone(Zone&&) = delete;
67 Zone& operator=(const Zone&) = delete;
68 Zone& operator=(Zone&&) = delete;
69 ~Zone() = default;
70
71 /**
72 * Constructor
73 * Parses and populates a zone from JSON object data
74 *
Matthew Barth4f0d3b72020-08-27 14:32:15 -050075 * @param[in] jsonObj - JSON object
Matthew Barth603ef162021-03-24 15:34:53 -050076 * @param[in] bus - sdbusplus bus object
77 * @param[in] event - sdeventplus event loop
78 * @param[in] mgr - Manager of this zone
Matthew Barth4f0d3b72020-08-27 14:32:15 -050079 */
Matthew Barth603ef162021-03-24 15:34:53 -050080 Zone(const json& jsonObj, sdbusplus::bus::bus& bus,
81 const sdeventplus::Event& event, Manager* mgr);
Matthew Barth4f0d3b72020-08-27 14:32:15 -050082
83 /**
Matthew Barthe47c9582021-03-09 14:24:02 -060084 * @brief Get the default ceiling
Matthew Barth4f0d3b72020-08-27 14:32:15 -050085 *
Matthew Barthe47c9582021-03-09 14:24:02 -060086 * Default ceiling is the highest target the fans within this zone is
87 * allowed to increase to. The zone's ceiling defaults to this unless
88 * changed by some configured event.
Matthew Barth4f0d3b72020-08-27 14:32:15 -050089 *
Matthew Barthe47c9582021-03-09 14:24:02 -060090 * @return Default ceiling of this zone
Matthew Barth4f0d3b72020-08-27 14:32:15 -050091 */
Matthew Barthe47c9582021-03-09 14:24:02 -060092 inline const auto& getDefaultCeiling() const
Matthew Barth4f0d3b72020-08-27 14:32:15 -050093 {
Matthew Barthe47c9582021-03-09 14:24:02 -060094 return _defaultCeiling;
Matthew Barth4f0d3b72020-08-27 14:32:15 -050095 }
96
97 /**
Matthew Barthe47c9582021-03-09 14:24:02 -060098 * @brief Get the default floor
Matthew Barth4f0d3b72020-08-27 14:32:15 -050099 *
Matthew Barthe47c9582021-03-09 14:24:02 -0600100 * The default floor is the lowest target the fans within this zone
101 * are allowed to decrease to. The zone's floor defaults to this
Matthew Barth4f0d3b72020-08-27 14:32:15 -0500102 * unless changed by some configured event.
103 *
Matthew Barthe47c9582021-03-09 14:24:02 -0600104 * @return Default floor
Matthew Barth4f0d3b72020-08-27 14:32:15 -0500105 */
106 inline const auto& getDefaultFloor() const
107 {
108 return _defaultFloor;
109 }
110
111 /**
Matthew Barthe47c9582021-03-09 14:24:02 -0600112 * @brief Get the increase delay(OPTIONAL)
Matthew Barth4f0d3b72020-08-27 14:32:15 -0500113 *
Matthew Barthe47c9582021-03-09 14:24:02 -0600114 * The increase delay is the amount of time(in seconds) increases
115 * to a target are delayed before being made. The default is 0, which
116 * results in immediate increase requests when any events result in
117 * a change to the target.
Matthew Barth4f0d3b72020-08-27 14:32:15 -0500118 *
119 * It is recommend a value other than 0 is configured, but that inherently
Matthew Barthe47c9582021-03-09 14:24:02 -0600120 * depends on the fan controller and configured increases.
Matthew Barth4f0d3b72020-08-27 14:32:15 -0500121 *
Matthew Barthe47c9582021-03-09 14:24:02 -0600122 * @return Increase delay(in seconds)
Matthew Barth4f0d3b72020-08-27 14:32:15 -0500123 */
124 inline const auto& getIncDelay() const
125 {
126 return _incDelay;
127 }
128
129 /**
Matthew Barthe47c9582021-03-09 14:24:02 -0600130 * @brief Get the decrease interval
Matthew Barth4f0d3b72020-08-27 14:32:15 -0500131 *
Matthew Barthe47c9582021-03-09 14:24:02 -0600132 * Decreases happen on a set interval when no requests for an increase
133 * in fan targets exists. This is the interval(in seconds) at which the fans
Matthew Barth4f0d3b72020-08-27 14:32:15 -0500134 * within the zone are decreased if events exist that result in a target
Matthew Barthe47c9582021-03-09 14:24:02 -0600135 * decrease.
Matthew Barth4f0d3b72020-08-27 14:32:15 -0500136 *
Matthew Barthe47c9582021-03-09 14:24:02 -0600137 * @return Decrease interval(in seconds)
Matthew Barth4f0d3b72020-08-27 14:32:15 -0500138 */
139 inline const auto& getDecInterval() const
140 {
141 return _decInterval;
142 }
143
Matthew Barth651f03a2020-08-27 16:15:11 -0500144 /**
Matthew Barthdc776c82021-02-25 16:06:16 -0600145 * @brief Get the target increase delta
146 *
147 * @return - The current target increase delta
148 */
149 inline auto& getIncDelta() const
150 {
151 return _incDelta;
152 };
153
154 /**
Matthew Barth45c44ea2021-03-03 13:16:14 -0600155 * @brief Get the target decrease delta
156 *
157 * @return - The current target decrease delta
158 */
159 inline auto& getDecDelta() const
160 {
161 return _decDelta;
162 };
163
164 /**
Matthew Barth603ef162021-03-24 15:34:53 -0500165 * @brief Get the manager of the zone
166 *
167 * @return - The manager of the zone
168 */
169 inline auto* getManager() const
170 {
171 return _manager;
172 }
173
174 /**
Matthew Barthde90fb42021-03-04 16:34:28 -0600175 * @brief Add a fan object to the zone
176 *
177 * @param[in] fan - Unique pointer to a fan object that will be moved into
178 * the zone
179 *
180 * Adds a fan object to the list of fans that make up the zone by moving the
181 * fan object into the list.
182 */
183 void addFan(std::unique_ptr<Fan> fan);
184
Matthew Barth12cb1252021-03-08 16:47:30 -0600185 /**
Matthew Barth8ba715e2021-03-05 09:00:05 -0600186 * Sets all fans in the zone to the target given when the zone is active
187 *
188 * @param[in] target - Target for fans
189 */
190 void setTarget(uint64_t target);
191
192 /**
193 * @brief Sets the automatic fan control allowed active state
194 *
195 * @param[in] ident - An identifier that affects the active state
196 * @param[in] isActiveAllow - Active state according to group
197 */
198 void setActiveAllow(const std::string& ident, bool isActiveAllow);
199
200 /**
Matthew Barth12cb1252021-03-08 16:47:30 -0600201 * @brief Set the floor to the given target and increase target to the floor
202 * when the target is below the floor value when floor changes are allowed.
203 *
204 * @param[in] target - Target to set the floor to
205 */
206 void setFloor(uint64_t target);
207
208 /**
209 * @brief Sets the floor change allowed state
210 *
211 * @param[in] ident - An identifier that affects floor changes
212 * @param[in] isAllow - Allow state according to the identifier
213 */
214 inline void setFloorChangeAllow(const std::string& ident, bool isAllow)
215 {
216 _floorChange[ident] = isAllow;
217 }
218
219 /**
Matthew Barth45c44ea2021-03-03 13:16:14 -0600220 * @brief Sets the decrease allowed state of a group
221 *
222 * @param[in] ident - An identifier that affects speed decreases
223 * @param[in] isAllow - Allow state according to the identifier
224 */
225 inline void setDecreaseAllow(const std::string& ident, bool isAllow)
226 {
227 _decAllowed[ident] = isAllow;
228 }
229
230 /**
Matthew Barth12cb1252021-03-08 16:47:30 -0600231 * @brief Calculate the requested target from the given delta and increases
232 * the fans, not going above the ceiling.
233 *
234 * @param[in] targetDelta - The delta to increase the target by
235 */
236 void requestIncrease(uint64_t targetDelta);
237
Matthew Bartha0dd1352021-03-09 11:10:49 -0600238 /**
Matthew Barth45c44ea2021-03-03 13:16:14 -0600239 * @brief Calculate the lowest requested decrease target from the given
240 * delta within a decrease interval.
241 *
242 * @param[in] targetDelta - The delta to decrease the target by
243 */
244 void requestDecrease(uint64_t targetDelta);
245
246 /**
Matthew Barth07fecfc2021-01-29 09:04:43 -0600247 * @brief Set the requested target base to be used as the target to base a
248 * new requested target from
249 *
250 * @param[in] targetBase - Base target value to use
251 */
252 inline void setRequestTargetBase(uint64_t targetBase)
253 {
254 _requestTargetBase = targetBase;
255 };
256
257 /**
Matthew Bartha0dd1352021-03-09 11:10:49 -0600258 * @brief Set a property to be persisted
259 *
260 * @param[in] intf - Interface containing property
261 * @param[in] prop - Property to be persisted
262 */
263 void setPersisted(const std::string& intf, const std::string& prop);
264
265 /**
266 * @brief Overridden thermal object's set 'Current' property function
267 *
268 * @param[in] value - Value to set 'Current' to
269 *
270 * @return - The updated value of the 'Current' property
271 */
272 std::string current(std::string value) override;
273
Matthew Barthb584d812021-03-11 15:55:04 -0600274 /**
275 * @brief A handler function to set/update a property on a zone
276 * @details Sets or updates a zone's dbus property to the given value using
277 * the provided base dbus object's set property function
278 *
279 * @param[in] intf - Interface on zone object
280 * @param[in] prop - Property on interface
281 * @param[in] func - Zone object's set property function pointer
282 * @param[in] value - Value to set property to
283 * @param[in] persist - Persist property value or not
284 *
285 * @return Lambda function
286 * A lambda function to set/update the zone's dbus property
287 */
288 template <typename T>
289 static auto setProperty(const char* intf, const char* prop,
290 T (Zone::*func)(T), T&& value, bool persist)
291 {
292 return [=, value = std::forward<T>(value)](Zone* zone) {
293 (zone->*func)(value);
294 if (persist)
295 {
296 zone->setPersisted(intf, prop);
297 }
298 };
299 }
300
301 /**
302 * @brief A handler function to set/update a zone's dbus property's persist
303 * state
304 * @details Sets or updates a zone's dbus property's persist state where the
305 * value of the property is to be left unchanged
306 *
307 * @param[in] intf - Interface on zone object
308 * @param[in] prop - Property on interface
309 * @param[in] persist - Persist property value or not
310 *
311 * @return Lambda function
312 * A lambda function to set/update the zone's dbus property's persist
313 * state
314 */
315 static auto setPropertyPersist(const char* intf, const char* prop,
316 bool persist)
317 {
318 return [=](Zone* zone) {
319 if (persist)
320 {
321 zone->setPersisted(intf, prop);
322 }
323 };
324 }
325
Matthew Barth4f0d3b72020-08-27 14:32:15 -0500326 private:
Matthew Barth603ef162021-03-24 15:34:53 -0500327 /* The zone's manager */
328 Manager* _manager;
329
Matthew Barthe47c9582021-03-09 14:24:02 -0600330 /* The zone's default ceiling value for fans */
331 uint64_t _defaultCeiling;
Matthew Barth4f0d3b72020-08-27 14:32:15 -0500332
Matthew Barthe47c9582021-03-09 14:24:02 -0600333 /* The zone's default floor value for fans */
Matthew Barth4f0d3b72020-08-27 14:32:15 -0500334 uint64_t _defaultFloor;
335
Matthew Barthe47c9582021-03-09 14:24:02 -0600336 /* Zone's increase delay(in seconds) (OPTIONAL) */
Matthew Barth4f0d3b72020-08-27 14:32:15 -0500337 uint64_t _incDelay;
338
Matthew Barthe47c9582021-03-09 14:24:02 -0600339 /* Zone's decrease interval(in seconds) */
Matthew Barth4f0d3b72020-08-27 14:32:15 -0500340 uint64_t _decInterval;
341
Matthew Barth12cb1252021-03-08 16:47:30 -0600342 /* The floor target to not go below */
343 uint64_t _floor;
344
345 /* Target for this zone */
346 uint64_t _target;
347
Matthew Barth2b3253e2021-03-09 14:51:16 -0600348 /* Zone increase delta */
349 uint64_t _incDelta;
350
Matthew Barth45c44ea2021-03-03 13:16:14 -0600351 /* Zone decrease delta */
352 uint64_t _decDelta;
353
Matthew Barth2b3253e2021-03-09 14:51:16 -0600354 /* The ceiling target to not go above */
355 uint64_t _ceiling;
356
357 /* Requested target base */
358 uint64_t _requestTargetBase;
359
Matthew Barth12cb1252021-03-08 16:47:30 -0600360 /* Map of whether floor changes are allowed by a string identifier */
361 std::map<std::string, bool> _floorChange;
362
Matthew Barth45c44ea2021-03-03 13:16:14 -0600363 /* Map of controlling decreases allowed by a string identifer */
364 std::map<std::string, bool> _decAllowed;
365
Matthew Bartha0dd1352021-03-09 11:10:49 -0600366 /* Map of interfaces to persisted properties the zone hosts*/
367 std::map<std::string, std::vector<std::string>> _propsPersisted;
368
Matthew Barth8ba715e2021-03-05 09:00:05 -0600369 /* Automatic fan control active state */
370 bool _isActive;
371
372 /* Map of active fan control allowed by a string identifier */
373 std::map<std::string, bool> _active;
374
Matthew Barthb584d812021-03-11 15:55:04 -0600375 /* Interface to property mapping of their associated set property handler
376 * function */
377 static const std::map<
378 std::string,
379 std::map<std::string,
380 std::function<std::function<void(Zone*)>(const json&, bool)>>>
Matthew Barth216229c2020-09-24 13:47:33 -0500381 _intfPropHandlers;
Matthew Barth651f03a2020-08-27 16:15:11 -0500382
Matthew Barthde90fb42021-03-04 16:34:28 -0600383 /* List of fans included in this zone */
384 std::vector<std::unique_ptr<Fan>> _fans;
385
Matthew Barth4f0d3b72020-08-27 14:32:15 -0500386 /**
Matthew Barthe47c9582021-03-09 14:24:02 -0600387 * @brief Parse and set the zone's default ceiling value
Matthew Barth4f0d3b72020-08-27 14:32:15 -0500388 *
389 * @param[in] jsonObj - JSON object for the zone
390 *
Matthew Barthe47c9582021-03-09 14:24:02 -0600391 * Sets the default ceiling value for the zone from the JSON configuration
392 * object
Matthew Barth4f0d3b72020-08-27 14:32:15 -0500393 */
Matthew Barthe47c9582021-03-09 14:24:02 -0600394 void setDefaultCeiling(const json& jsonObj);
Matthew Barth4f0d3b72020-08-27 14:32:15 -0500395
396 /**
Matthew Barthe47c9582021-03-09 14:24:02 -0600397 * @brief Parse and set the zone's default floor value
Matthew Barth4f0d3b72020-08-27 14:32:15 -0500398 *
399 * @param[in] jsonObj - JSON object for the zone
400 *
Matthew Barthe47c9582021-03-09 14:24:02 -0600401 * Sets the default floor value for the zone from the JSON configuration
402 * object
Matthew Barth4f0d3b72020-08-27 14:32:15 -0500403 */
404 void setDefaultFloor(const json& jsonObj);
405
406 /**
407 * @brief Parse and set the zone's decrease interval(in seconds)
408 *
409 * @param[in] jsonObj - JSON object for the zone
410 *
Matthew Barthe47c9582021-03-09 14:24:02 -0600411 * Sets the decrease interval(in seconds) for the zone from the JSON
Matthew Barth4f0d3b72020-08-27 14:32:15 -0500412 * configuration object
413 */
414 void setDecInterval(const json& jsonObj);
Matthew Barth651f03a2020-08-27 16:15:11 -0500415
416 /**
Matthew Barth216229c2020-09-24 13:47:33 -0500417 * @brief Parse and set the interfaces served by the zone(OPTIONAL)
Matthew Barth651f03a2020-08-27 16:15:11 -0500418 *
419 * @param[in] jsonObj - JSON object for the zone
420 *
Matthew Barth216229c2020-09-24 13:47:33 -0500421 * Constructs any zone interface handler functions for interfaces that the
422 * zone serves which contains the interface's property's value and
423 * persistency state (OPTIONAL). A property's "persist" state is defaulted
424 * to not be persisted when not given.
Matthew Barth651f03a2020-08-27 16:15:11 -0500425 */
426 void setInterfaces(const json& jsonObj);
Matthew Bartha0dd1352021-03-09 11:10:49 -0600427
428 /**
429 * @brief Is the property persisted
430 *
431 * @param[in] intf - Interface containing property
432 * @param[in] prop - Property to check if persisted
433 *
434 * @return - True if property is to be persisted, false otherwise
435 */
436 bool isPersisted(const std::string& intf, const std::string& prop);
437
438 /**
439 * @brief Save the thermal control current mode property to persisted
440 * storage
441 */
442 void saveCurrentMode();
Matthew Barth2b3253e2021-03-09 14:51:16 -0600443
444 /**
445 * @brief Get the request target base if defined, otherwise the the current
446 * target is returned
447 *
448 * @return - The request target base or current target
449 */
450 inline auto getRequestTargetBase() const
451 {
452 return (_requestTargetBase != 0) ? _requestTargetBase : _target;
453 };
Matthew Barth4f0d3b72020-08-27 14:32:15 -0500454};
455
Matthew Barth651f03a2020-08-27 16:15:11 -0500456/**
457 * Properties of interfaces supported by the zone configuration
458 */
459namespace zone::property
460{
461
462/**
Matthew Barth216229c2020-09-24 13:47:33 -0500463 * @brief "Supported" property on the "xyz.openbmc_project.Control.ThermalMode"
Matthew Barthb584d812021-03-11 15:55:04 -0600464 * interface parser. Also creates the handler function for the Zone object to
465 * initialize the property according to what's parsed from the configuration.
Matthew Barth651f03a2020-08-27 16:15:11 -0500466 *
467 * @param[in] jsonObj - JSON object for the "Supported" property
Matthew Barth216229c2020-09-24 13:47:33 -0500468 * @param[in] persist - Whether to persist the value or not
Matthew Barth651f03a2020-08-27 16:15:11 -0500469 *
Matthew Barthb584d812021-03-11 15:55:04 -0600470 * @return Zone interface set property handler function for the "Supported"
471 * property
Matthew Barth651f03a2020-08-27 16:15:11 -0500472 */
Matthew Barthb584d812021-03-11 15:55:04 -0600473std::function<void(Zone*)> supported(const json& jsonObj, bool persist);
Matthew Barth651f03a2020-08-27 16:15:11 -0500474
475/**
Matthew Barth216229c2020-09-24 13:47:33 -0500476 * @brief "Current" property on the "xyz.openbmc_project.Control.ThermalMode"
Matthew Barthb584d812021-03-11 15:55:04 -0600477 * interface parser. Also creates the handler function for the Zone object to
478 * initialize the property according to what's parsed from the configuration.
Matthew Barth651f03a2020-08-27 16:15:11 -0500479 *
480 * @param[in] jsonObj - JSON object for the "Current" property
Matthew Barth216229c2020-09-24 13:47:33 -0500481 * @param[in] persist - Whether to persist the value or not
Matthew Barth651f03a2020-08-27 16:15:11 -0500482 *
Matthew Barthb584d812021-03-11 15:55:04 -0600483 * @return Zone interface set property handler function for the "Current"
484 * property
Matthew Barth651f03a2020-08-27 16:15:11 -0500485 */
Matthew Barthb584d812021-03-11 15:55:04 -0600486std::function<void(Zone*)> current(const json& jsonObj, bool persist);
Matthew Barth651f03a2020-08-27 16:15:11 -0500487
488} // namespace zone::property
489
Matthew Barth4f0d3b72020-08-27 14:32:15 -0500490} // namespace phosphor::fan::control::json