blob: b079bf47e36da48e4667e10e2861b65616f23f3d [file] [log] [blame]
Matthew Barth17d1fe22017-05-11 15:00:36 -05001#pragma once
2
3#include <algorithm>
Matthew Barth4af419c2017-06-12 13:39:31 -05004#include <numeric>
Matthew Barthb280bfa2017-09-15 09:56:50 -05005#include "types.hpp"
6#include "zone.hpp"
Matthew Barth17d1fe22017-05-11 15:00:36 -05007
8namespace phosphor
9{
10namespace fan
11{
12namespace control
13{
14namespace action
15{
16
17/**
Matthew Barth2a646c52017-10-05 17:04:11 -050018 * @brief An action that wraps a list of actions with a timer
19 * @details Sets up a list of actions to be invoked when the defined timer
20 * expires (or for each expiration of a repeating timer).
21 *
22 * @param[in] tConf - Timer configuration parameters
23 * @param[in] action - List of actions to be called when the timer expires
24 *
25 * @return Action lambda function
26 * An Action function that creates a timer
27 */
28Action call_actions_based_on_timer(
29 Timer&& tConf,
30 std::vector<Action>&& actions);
31
32/**
Matthew Barth98726c42017-10-17 10:35:20 -050033 * @brief An action that sets the floor to the default fan floor speed
34 * @details Sets the fan floor to the defined default fan floor speed when a
35 * service associated to the given group has terminated. Once all services
36 * are functional and providing the sensors again, the fan floor is allowed
37 * to be set normally.
38 *
39 * @param[in] zone - Zone containing fans
40 * @param[in] group - Group of sensors to determine services' states
41 */
42void default_floor_on_missing_owner(Zone& zone, const Group& group);
43
44/**
Matthew Barth0decd1b2017-10-24 15:58:17 -050045 * @brief An action to set a speed when a service owner is missing
46 * @details Sets the fans to the given speed when any service owner associated
47 * to the group is missing. Once all services are functional and providing
48 * the event data again, active fan speed changes are allowed.
49 *
50 * @param[in] speed - Speed to set the zone to
51 *
52 * @return Action lambda function
53 * An Action function that sets the zone to the given speed if any service
54 * owners are missing.
55 */
56Action set_speed_on_missing_owner(uint64_t speed);
57
58/**
Matthew Barthb280bfa2017-09-15 09:56:50 -050059 * @brief An action to set the request speed base
60 * @details A new target speed is determined using a speed delta being added
61 * or subtracted, for increases or decrease respectively, from a base speed.
62 * This base speed defaults to be the current target speed or is set to a
63 * different base speed(i.e. the fans' tach feedback speed) to request a new
64 * target from.
65 *
66 * @param[in] zone - Zone containing fans
67 * @param[in] group - Group of sensors to determine base from
68 */
69void set_request_speed_base_with_max(Zone& zone, const Group& group);
70
71/**
Matthew Barth17d1fe22017-05-11 15:00:36 -050072 * @brief An action to set the speed on a zone
Matthew Barth861d77c2017-05-22 14:18:25 -050073 * @details The zone is held at the given speed when a defined number of
Matthew Barth17d1fe22017-05-11 15:00:36 -050074 * properties in the group are set to the given state
75 *
76 * @param[in] count - Number of properties
77 * @param[in] state - Value the property(s) needed to be set at
78 * @param[in] speed - Speed to set the zone to
79 *
80 * @return Lambda function
81 * A lambda function to set the zone speed when the number of properties
82 * within the group are at a certain value
83 */
Matthew Barth9e741ed2017-06-02 16:29:09 -050084template <typename T>
85auto count_state_before_speed(size_t count, T&& state, uint64_t speed)
Matthew Barth17d1fe22017-05-11 15:00:36 -050086{
Matthew Barth9e741ed2017-06-02 16:29:09 -050087 return [count,
88 speed,
89 state = std::forward<T>(state)](auto& zone, auto& group)
Matthew Barth17d1fe22017-05-11 15:00:36 -050090 {
Matthew Barthe0f67c82018-05-08 15:47:12 -050091 size_t numAtState = 0;
92 for (auto& entry : group)
Matthew Barth17d1fe22017-05-11 15:00:36 -050093 {
Matthew Barthe0f67c82018-05-08 15:47:12 -050094 try
95 {
96 if (zone.template getPropertyValue<T>(
97 entry.first,
98 std::get<intfPos>(entry.second),
99 std::get<propPos>(entry.second)) == state)
100 {
101 numAtState++;
102 }
103 }
104 catch (const std::out_of_range& oore)
105 {
106 // Default to property not equal when not found
107 }
108 if (numAtState >= count)
109 {
110 zone.setSpeed(speed);
111 break;
112 }
Matthew Barth17d1fe22017-05-11 15:00:36 -0500113 }
Matthew Barth60b00762017-08-15 13:39:06 -0500114 // Update group's fan control active allowed based on action results
115 zone.setActiveAllow(&group, !(numAtState >= count));
Matthew Barth17d1fe22017-05-11 15:00:36 -0500116 };
117}
118
Matthew Barth4af419c2017-06-12 13:39:31 -0500119/**
120 * @brief An action to set the floor speed on a zone
121 * @details Based on the average of the defined sensor group values, the floor
122 * speed is selected from the first map key entry that the average sensor value
123 * is less than.
124 *
125 * @param[in] val_to_speed - Ordered map of sensor value-to-speed
126 *
Matthew Barthb280bfa2017-09-15 09:56:50 -0500127 * @return Action lambda function
128 * An Action function to set the zone's floor speed when the average of
Matthew Barth4af419c2017-06-12 13:39:31 -0500129 * property values within the group is below the lowest sensor value given
130 */
Matthew Barthb280bfa2017-09-15 09:56:50 -0500131Action set_floor_from_average_sensor_value(
132 std::map<int64_t, uint64_t>&& val_to_speed);
Matthew Barth4af419c2017-06-12 13:39:31 -0500133
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500134/**
135 * @brief An action to set the ceiling speed on a zone
Matthew Barthb280bfa2017-09-15 09:56:50 -0500136 * @details Based on the average of the defined sensor group values, the
137 * ceiling speed is selected from the map key transition point that the average
138 * sensor value falls within depending on the key values direction from what
139 * was previously read.
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500140 *
141 * @param[in] val_to_speed - Ordered map of sensor value-to-speed transitions
142 *
Matthew Barthb280bfa2017-09-15 09:56:50 -0500143 * @return Action lambda function
144 * An Action function to set the zone's ceiling speed when the average of
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500145 * property values within the group is above(increasing) or
146 * below(decreasing) the key transition point
147 */
Matthew Barthb280bfa2017-09-15 09:56:50 -0500148Action set_ceiling_from_average_sensor_value(
149 std::map<int64_t, uint64_t>&& val_to_speed);
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500150
Matthew Barth24623522017-06-21 14:09:57 -0500151/**
152 * @brief An action to set the speed increase delta and request speed change
153 * @details Provides the ability to determine what the net increase delta the
154 * zone's fan speeds should be updated by from their current target speed and
155 * request that new target speed.
156 *
157 * @param[in] state - State to compare the group's property value to
Matthew Barth172f3932017-08-14 11:07:46 -0500158 * @param[in] factor - Factor to apply to the calculated net delta
Matthew Barth24623522017-06-21 14:09:57 -0500159 * @param[in] speedDelta - Speed delta of the group
160 *
161 * @return Lambda function
162 * A lambda function that determines the net increase delta and requests
163 * a new target speed with that increase for the zone.
164 */
165template <typename T>
Matthew Barth172f3932017-08-14 11:07:46 -0500166auto set_net_increase_speed(T&& state, T&& factor, uint64_t speedDelta)
Matthew Barth24623522017-06-21 14:09:57 -0500167{
168 return [speedDelta,
Matthew Barth172f3932017-08-14 11:07:46 -0500169 factor = std::forward<T>(factor),
Matthew Barth24623522017-06-21 14:09:57 -0500170 state = std::forward<T>(state)](auto& zone, auto& group)
171 {
172 auto netDelta = zone.getIncSpeedDelta();
173 std::for_each(
174 group.begin(),
175 group.end(),
Matthew Barth172f3932017-08-14 11:07:46 -0500176 [&zone, &state, &factor, &speedDelta, &netDelta](
Matthew Barthbc651602017-08-10 16:59:43 -0500177 auto const& entry)
Matthew Barth24623522017-06-21 14:09:57 -0500178 {
Matthew Barthbc651602017-08-10 16:59:43 -0500179 try
Matthew Barth24623522017-06-21 14:09:57 -0500180 {
Matthew Barthbc651602017-08-10 16:59:43 -0500181 T value = zone.template getPropertyValue<T>(
182 entry.first,
183 std::get<intfPos>(entry.second),
184 std::get<propPos>(entry.second));
185 // TODO openbmc/phosphor-fan-presence#7 - Support possible
186 // state types for comparison
187 if (value >= state)
188 {
Matthew Barth172f3932017-08-14 11:07:46 -0500189 // Increase by at least a single delta(factor)
Matthew Barthbc651602017-08-10 16:59:43 -0500190 // to attempt bringing under 'state'
Matthew Barth172f3932017-08-14 11:07:46 -0500191 auto delta = std::max(
192 (value - state),
193 factor);
194 // Increase is the factor applied to the
195 // difference times the given speed delta
196 netDelta = std::max(
197 netDelta,
198 (delta/factor) * speedDelta);
Matthew Barthbc651602017-08-10 16:59:43 -0500199 }
200 }
201 catch (const std::out_of_range& oore)
202 {
203 // Property value not found, netDelta unchanged
Matthew Barth24623522017-06-21 14:09:57 -0500204 }
205 }
206 );
Matthew Barth240397b2017-06-22 11:23:30 -0500207 // Request speed change for target speed update
208 zone.requestSpeedIncrease(netDelta);
Matthew Barth24623522017-06-21 14:09:57 -0500209 };
210}
211
Matthew Barth0ce99d82017-06-22 15:07:29 -0500212/**
213 * @brief An action to set the speed decrease delta and request speed change
214 * @details Provides the ability to determine what the net decrease delta each
215 * zone's fan speeds should be updated by from their current target speed, and
216 * request that speed change occur on the next decrease interval.
217 *
218 * @param[in] state - State to compare the group's property value to
Matthew Barth172f3932017-08-14 11:07:46 -0500219 * @param[in] factor - Factor to apply to the calculated net delta
Matthew Barth0ce99d82017-06-22 15:07:29 -0500220 * @param[in] speedDelta - Speed delta of the group
221 *
222 * @return Lambda function
223 * A lambda function that determines the net decrease delta and requests
224 * a new target speed with that decrease for the zone.
225 */
226template <typename T>
Matthew Barth172f3932017-08-14 11:07:46 -0500227auto set_net_decrease_speed(T&& state, T&& factor, uint64_t speedDelta)
Matthew Barth0ce99d82017-06-22 15:07:29 -0500228{
229 return [speedDelta,
Matthew Barth172f3932017-08-14 11:07:46 -0500230 factor = std::forward<T>(factor),
Matthew Barth0ce99d82017-06-22 15:07:29 -0500231 state = std::forward<T>(state)](auto& zone, auto& group)
232 {
233 auto netDelta = zone.getDecSpeedDelta();
Matthew Barthe4338cd2017-12-14 11:14:30 -0600234 for (auto& entry : group)
235 {
236 try
Matthew Barth0ce99d82017-06-22 15:07:29 -0500237 {
Matthew Barthe4338cd2017-12-14 11:14:30 -0600238 T value = zone.template getPropertyValue<T>(
239 entry.first,
240 std::get<intfPos>(entry.second),
241 std::get<propPos>(entry.second));
242 // TODO openbmc/phosphor-fan-presence#7 - Support possible
243 // state types for comparison
244 if (value < state)
Matthew Barth0ce99d82017-06-22 15:07:29 -0500245 {
Matthew Barthe4338cd2017-12-14 11:14:30 -0600246 if (netDelta == 0)
Matthew Barth0ce99d82017-06-22 15:07:29 -0500247 {
Matthew Barthe4338cd2017-12-14 11:14:30 -0600248 netDelta = ((state - value)/factor) * speedDelta;
249 }
250 else
251 {
252 // Decrease is the factor applied to the
253 // difference times the given speed delta
254 netDelta = std::min(
255 netDelta,
256 ((state - value)/factor) * speedDelta);
Matthew Barth0ce99d82017-06-22 15:07:29 -0500257 }
Matthew Barthbc651602017-08-10 16:59:43 -0500258 }
Matthew Barthe4338cd2017-12-14 11:14:30 -0600259 else
Matthew Barthbc651602017-08-10 16:59:43 -0500260 {
Matthew Barthe4338cd2017-12-14 11:14:30 -0600261 // No decrease allowed for this group
262 netDelta = 0;
263 break;
Matthew Barth0ce99d82017-06-22 15:07:29 -0500264 }
265 }
Matthew Barthe4338cd2017-12-14 11:14:30 -0600266 catch (const std::out_of_range& oore)
267 {
268 // Property value not found, netDelta unchanged
269 }
270 }
271 // Update group's decrease allowed state
272 zone.setDecreaseAllow(&group, !(netDelta == 0));
Matthew Barth0ce99d82017-06-22 15:07:29 -0500273 // Request speed decrease to occur on decrease interval
274 zone.requestSpeedDecrease(netDelta);
275 };
276}
277
Matthew Barth17d1fe22017-05-11 15:00:36 -0500278} // namespace action
279} // namespace control
280} // namespace fan
281} // namespace phosphor