blob: 3061814adc7701b55ae3c90c028774678e3dc7b5 [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 Barthb280bfa2017-09-15 09:56:50 -050018 * @brief An action to set the request speed base
19 * @details A new target speed is determined using a speed delta being added
20 * or subtracted, for increases or decrease respectively, from a base speed.
21 * This base speed defaults to be the current target speed or is set to a
22 * different base speed(i.e. the fans' tach feedback speed) to request a new
23 * target from.
24 *
25 * @param[in] zone - Zone containing fans
26 * @param[in] group - Group of sensors to determine base from
27 */
28void set_request_speed_base_with_max(Zone& zone, const Group& group);
29
30/**
Matthew Barth17d1fe22017-05-11 15:00:36 -050031 * @brief An action to set the speed on a zone
Matthew Barth861d77c2017-05-22 14:18:25 -050032 * @details The zone is held at the given speed when a defined number of
Matthew Barth17d1fe22017-05-11 15:00:36 -050033 * properties in the group are set to the given state
34 *
35 * @param[in] count - Number of properties
36 * @param[in] state - Value the property(s) needed to be set at
37 * @param[in] speed - Speed to set the zone to
38 *
39 * @return Lambda function
40 * A lambda function to set the zone speed when the number of properties
41 * within the group are at a certain value
42 */
Matthew Barth9e741ed2017-06-02 16:29:09 -050043template <typename T>
44auto count_state_before_speed(size_t count, T&& state, uint64_t speed)
Matthew Barth17d1fe22017-05-11 15:00:36 -050045{
Matthew Barth9e741ed2017-06-02 16:29:09 -050046 return [count,
47 speed,
48 state = std::forward<T>(state)](auto& zone, auto& group)
Matthew Barth17d1fe22017-05-11 15:00:36 -050049 {
50 size_t numAtState = std::count_if(
51 group.begin(),
52 group.end(),
53 [&zone, &state](auto const& entry)
54 {
Matthew Barthbc651602017-08-10 16:59:43 -050055 try
56 {
57 return zone.template getPropertyValue<T>(
58 entry.first,
59 std::get<intfPos>(entry.second),
60 std::get<propPos>(entry.second)) == state;
61 }
62 catch (const std::out_of_range& oore)
63 {
64 // Default to property not equal when not found
65 return false;
66 }
Matthew Barth17d1fe22017-05-11 15:00:36 -050067 });
Matthew Barth17d1fe22017-05-11 15:00:36 -050068 if (numAtState >= count)
69 {
70 zone.setSpeed(speed);
71 }
Matthew Barth60b00762017-08-15 13:39:06 -050072 // Update group's fan control active allowed based on action results
73 zone.setActiveAllow(&group, !(numAtState >= count));
Matthew Barth17d1fe22017-05-11 15:00:36 -050074 };
75}
76
Matthew Barth4af419c2017-06-12 13:39:31 -050077/**
78 * @brief An action to set the floor speed on a zone
79 * @details Based on the average of the defined sensor group values, the floor
80 * speed is selected from the first map key entry that the average sensor value
81 * is less than.
82 *
83 * @param[in] val_to_speed - Ordered map of sensor value-to-speed
84 *
Matthew Barthb280bfa2017-09-15 09:56:50 -050085 * @return Action lambda function
86 * An Action function to set the zone's floor speed when the average of
Matthew Barth4af419c2017-06-12 13:39:31 -050087 * property values within the group is below the lowest sensor value given
88 */
Matthew Barthb280bfa2017-09-15 09:56:50 -050089Action set_floor_from_average_sensor_value(
90 std::map<int64_t, uint64_t>&& val_to_speed);
Matthew Barth4af419c2017-06-12 13:39:31 -050091
Matthew Barthe0ca13e2017-06-13 16:29:09 -050092/**
93 * @brief An action to set the ceiling speed on a zone
Matthew Barthb280bfa2017-09-15 09:56:50 -050094 * @details Based on the average of the defined sensor group values, the
95 * ceiling speed is selected from the map key transition point that the average
96 * sensor value falls within depending on the key values direction from what
97 * was previously read.
Matthew Barthe0ca13e2017-06-13 16:29:09 -050098 *
99 * @param[in] val_to_speed - Ordered map of sensor value-to-speed transitions
100 *
Matthew Barthb280bfa2017-09-15 09:56:50 -0500101 * @return Action lambda function
102 * An Action function to set the zone's ceiling speed when the average of
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500103 * property values within the group is above(increasing) or
104 * below(decreasing) the key transition point
105 */
Matthew Barthb280bfa2017-09-15 09:56:50 -0500106Action set_ceiling_from_average_sensor_value(
107 std::map<int64_t, uint64_t>&& val_to_speed);
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500108
Matthew Barth24623522017-06-21 14:09:57 -0500109/**
110 * @brief An action to set the speed increase delta and request speed change
111 * @details Provides the ability to determine what the net increase delta the
112 * zone's fan speeds should be updated by from their current target speed and
113 * request that new target speed.
114 *
115 * @param[in] state - State to compare the group's property value to
Matthew Barth172f3932017-08-14 11:07:46 -0500116 * @param[in] factor - Factor to apply to the calculated net delta
Matthew Barth24623522017-06-21 14:09:57 -0500117 * @param[in] speedDelta - Speed delta of the group
118 *
119 * @return Lambda function
120 * A lambda function that determines the net increase delta and requests
121 * a new target speed with that increase for the zone.
122 */
123template <typename T>
Matthew Barth172f3932017-08-14 11:07:46 -0500124auto set_net_increase_speed(T&& state, T&& factor, uint64_t speedDelta)
Matthew Barth24623522017-06-21 14:09:57 -0500125{
126 return [speedDelta,
Matthew Barth172f3932017-08-14 11:07:46 -0500127 factor = std::forward<T>(factor),
Matthew Barth24623522017-06-21 14:09:57 -0500128 state = std::forward<T>(state)](auto& zone, auto& group)
129 {
130 auto netDelta = zone.getIncSpeedDelta();
131 std::for_each(
132 group.begin(),
133 group.end(),
Matthew Barth172f3932017-08-14 11:07:46 -0500134 [&zone, &state, &factor, &speedDelta, &netDelta](
Matthew Barthbc651602017-08-10 16:59:43 -0500135 auto const& entry)
Matthew Barth24623522017-06-21 14:09:57 -0500136 {
Matthew Barthbc651602017-08-10 16:59:43 -0500137 try
Matthew Barth24623522017-06-21 14:09:57 -0500138 {
Matthew Barthbc651602017-08-10 16:59:43 -0500139 T value = zone.template getPropertyValue<T>(
140 entry.first,
141 std::get<intfPos>(entry.second),
142 std::get<propPos>(entry.second));
143 // TODO openbmc/phosphor-fan-presence#7 - Support possible
144 // state types for comparison
145 if (value >= state)
146 {
Matthew Barth172f3932017-08-14 11:07:46 -0500147 // Increase by at least a single delta(factor)
Matthew Barthbc651602017-08-10 16:59:43 -0500148 // to attempt bringing under 'state'
Matthew Barth172f3932017-08-14 11:07:46 -0500149 auto delta = std::max(
150 (value - state),
151 factor);
152 // Increase is the factor applied to the
153 // difference times the given speed delta
154 netDelta = std::max(
155 netDelta,
156 (delta/factor) * speedDelta);
Matthew Barthbc651602017-08-10 16:59:43 -0500157 }
158 }
159 catch (const std::out_of_range& oore)
160 {
161 // Property value not found, netDelta unchanged
Matthew Barth24623522017-06-21 14:09:57 -0500162 }
163 }
164 );
Matthew Barth240397b2017-06-22 11:23:30 -0500165 // Request speed change for target speed update
166 zone.requestSpeedIncrease(netDelta);
Matthew Barth24623522017-06-21 14:09:57 -0500167 };
168}
169
Matthew Barth0ce99d82017-06-22 15:07:29 -0500170/**
171 * @brief An action to set the speed decrease delta and request speed change
172 * @details Provides the ability to determine what the net decrease delta each
173 * zone's fan speeds should be updated by from their current target speed, and
174 * request that speed change occur on the next decrease interval.
175 *
176 * @param[in] state - State to compare the group's property value to
Matthew Barth172f3932017-08-14 11:07:46 -0500177 * @param[in] factor - Factor to apply to the calculated net delta
Matthew Barth0ce99d82017-06-22 15:07:29 -0500178 * @param[in] speedDelta - Speed delta of the group
179 *
180 * @return Lambda function
181 * A lambda function that determines the net decrease delta and requests
182 * a new target speed with that decrease for the zone.
183 */
184template <typename T>
Matthew Barth172f3932017-08-14 11:07:46 -0500185auto set_net_decrease_speed(T&& state, T&& factor, uint64_t speedDelta)
Matthew Barth0ce99d82017-06-22 15:07:29 -0500186{
187 return [speedDelta,
Matthew Barth172f3932017-08-14 11:07:46 -0500188 factor = std::forward<T>(factor),
Matthew Barth0ce99d82017-06-22 15:07:29 -0500189 state = std::forward<T>(state)](auto& zone, auto& group)
190 {
191 auto netDelta = zone.getDecSpeedDelta();
192 std::for_each(
193 group.begin(),
194 group.end(),
Matthew Barth172f3932017-08-14 11:07:46 -0500195 [&zone, &state, &factor, &speedDelta, &netDelta](auto const& entry)
Matthew Barth0ce99d82017-06-22 15:07:29 -0500196 {
Matthew Barthbc651602017-08-10 16:59:43 -0500197 try
Matthew Barth0ce99d82017-06-22 15:07:29 -0500198 {
Matthew Barthbc651602017-08-10 16:59:43 -0500199 T value = zone.template getPropertyValue<T>(
200 entry.first,
201 std::get<intfPos>(entry.second),
202 std::get<propPos>(entry.second));
203 // TODO openbmc/phosphor-fan-presence#7 - Support possible
204 // state types for comparison
205 if (value < state)
Matthew Barth0ce99d82017-06-22 15:07:29 -0500206 {
Matthew Barthbc651602017-08-10 16:59:43 -0500207 if (netDelta == 0)
208 {
Matthew Barth172f3932017-08-14 11:07:46 -0500209 netDelta = ((state - value)/factor) * speedDelta;
Matthew Barthbc651602017-08-10 16:59:43 -0500210 }
211 else
212 {
Matthew Barth172f3932017-08-14 11:07:46 -0500213 // Decrease is the factor applied to the
214 // difference times the given speed delta
215 netDelta = std::min(
216 netDelta,
217 ((state - value)/factor) * speedDelta);
Matthew Barthbc651602017-08-10 16:59:43 -0500218 }
Matthew Barth0ce99d82017-06-22 15:07:29 -0500219 }
Matthew Barthbc651602017-08-10 16:59:43 -0500220 }
221 catch (const std::out_of_range& oore)
222 {
223 // Property value not found, netDelta unchanged
Matthew Barth0ce99d82017-06-22 15:07:29 -0500224 }
225 }
226 );
227 // Request speed decrease to occur on decrease interval
228 zone.requestSpeedDecrease(netDelta);
229 };
230}
231
Matthew Barth17d1fe22017-05-11 15:00:36 -0500232} // namespace action
233} // namespace control
234} // namespace fan
235} // namespace phosphor