1 #pragma once 2 3 #include <algorithm> 4 #include <numeric> 5 #include "types.hpp" 6 #include "zone.hpp" 7 8 namespace phosphor 9 { 10 namespace fan 11 { 12 namespace control 13 { 14 namespace action 15 { 16 17 /** 18 * @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 */ 28 Action call_actions_based_on_timer( 29 Timer&& tConf, 30 std::vector<Action>&& actions); 31 32 /** 33 * @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 */ 42 void default_floor_on_missing_owner(Zone& zone, const Group& group); 43 44 /** 45 * @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 */ 56 Action set_speed_on_missing_owner(uint64_t speed); 57 58 /** 59 * @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 */ 69 void set_request_speed_base_with_max(Zone& zone, const Group& group); 70 71 /** 72 * @brief An action to set the speed on a zone 73 * @details The zone is held at the given speed when a defined number of 74 * 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 */ 84 template <typename T> 85 auto count_state_before_speed(size_t count, T&& state, uint64_t speed) 86 { 87 return [count, 88 speed, 89 state = std::forward<T>(state)](auto& zone, auto& group) 90 { 91 size_t numAtState = std::count_if( 92 group.begin(), 93 group.end(), 94 [&zone, &state](auto const& entry) 95 { 96 try 97 { 98 return zone.template getPropertyValue<T>( 99 entry.first, 100 std::get<intfPos>(entry.second), 101 std::get<propPos>(entry.second)) == state; 102 } 103 catch (const std::out_of_range& oore) 104 { 105 // Default to property not equal when not found 106 return false; 107 } 108 }); 109 if (numAtState >= count) 110 { 111 zone.setSpeed(speed); 112 } 113 // Update group's fan control active allowed based on action results 114 zone.setActiveAllow(&group, !(numAtState >= count)); 115 }; 116 } 117 118 /** 119 * @brief An action to set the floor speed on a zone 120 * @details Based on the average of the defined sensor group values, the floor 121 * speed is selected from the first map key entry that the average sensor value 122 * is less than. 123 * 124 * @param[in] val_to_speed - Ordered map of sensor value-to-speed 125 * 126 * @return Action lambda function 127 * An Action function to set the zone's floor speed when the average of 128 * property values within the group is below the lowest sensor value given 129 */ 130 Action set_floor_from_average_sensor_value( 131 std::map<int64_t, uint64_t>&& val_to_speed); 132 133 /** 134 * @brief An action to set the ceiling speed on a zone 135 * @details Based on the average of the defined sensor group values, the 136 * ceiling speed is selected from the map key transition point that the average 137 * sensor value falls within depending on the key values direction from what 138 * was previously read. 139 * 140 * @param[in] val_to_speed - Ordered map of sensor value-to-speed transitions 141 * 142 * @return Action lambda function 143 * An Action function to set the zone's ceiling speed when the average of 144 * property values within the group is above(increasing) or 145 * below(decreasing) the key transition point 146 */ 147 Action set_ceiling_from_average_sensor_value( 148 std::map<int64_t, uint64_t>&& val_to_speed); 149 150 /** 151 * @brief An action to set the speed increase delta and request speed change 152 * @details Provides the ability to determine what the net increase delta the 153 * zone's fan speeds should be updated by from their current target speed and 154 * request that new target speed. 155 * 156 * @param[in] state - State to compare the group's property value to 157 * @param[in] factor - Factor to apply to the calculated net delta 158 * @param[in] speedDelta - Speed delta of the group 159 * 160 * @return Lambda function 161 * A lambda function that determines the net increase delta and requests 162 * a new target speed with that increase for the zone. 163 */ 164 template <typename T> 165 auto set_net_increase_speed(T&& state, T&& factor, uint64_t speedDelta) 166 { 167 return [speedDelta, 168 factor = std::forward<T>(factor), 169 state = std::forward<T>(state)](auto& zone, auto& group) 170 { 171 auto netDelta = zone.getIncSpeedDelta(); 172 std::for_each( 173 group.begin(), 174 group.end(), 175 [&zone, &state, &factor, &speedDelta, &netDelta]( 176 auto const& entry) 177 { 178 try 179 { 180 T value = zone.template getPropertyValue<T>( 181 entry.first, 182 std::get<intfPos>(entry.second), 183 std::get<propPos>(entry.second)); 184 // TODO openbmc/phosphor-fan-presence#7 - Support possible 185 // state types for comparison 186 if (value >= state) 187 { 188 // Increase by at least a single delta(factor) 189 // to attempt bringing under 'state' 190 auto delta = std::max( 191 (value - state), 192 factor); 193 // Increase is the factor applied to the 194 // difference times the given speed delta 195 netDelta = std::max( 196 netDelta, 197 (delta/factor) * speedDelta); 198 } 199 } 200 catch (const std::out_of_range& oore) 201 { 202 // Property value not found, netDelta unchanged 203 } 204 } 205 ); 206 // Request speed change for target speed update 207 zone.requestSpeedIncrease(netDelta); 208 }; 209 } 210 211 /** 212 * @brief An action to set the speed decrease delta and request speed change 213 * @details Provides the ability to determine what the net decrease delta each 214 * zone's fan speeds should be updated by from their current target speed, and 215 * request that speed change occur on the next decrease interval. 216 * 217 * @param[in] state - State to compare the group's property value to 218 * @param[in] factor - Factor to apply to the calculated net delta 219 * @param[in] speedDelta - Speed delta of the group 220 * 221 * @return Lambda function 222 * A lambda function that determines the net decrease delta and requests 223 * a new target speed with that decrease for the zone. 224 */ 225 template <typename T> 226 auto set_net_decrease_speed(T&& state, T&& factor, uint64_t speedDelta) 227 { 228 return [speedDelta, 229 factor = std::forward<T>(factor), 230 state = std::forward<T>(state)](auto& zone, auto& group) 231 { 232 auto netDelta = zone.getDecSpeedDelta(); 233 for (auto& entry : group) 234 { 235 try 236 { 237 T value = zone.template getPropertyValue<T>( 238 entry.first, 239 std::get<intfPos>(entry.second), 240 std::get<propPos>(entry.second)); 241 // TODO openbmc/phosphor-fan-presence#7 - Support possible 242 // state types for comparison 243 if (value < state) 244 { 245 if (netDelta == 0) 246 { 247 netDelta = ((state - value)/factor) * speedDelta; 248 } 249 else 250 { 251 // Decrease is the factor applied to the 252 // difference times the given speed delta 253 netDelta = std::min( 254 netDelta, 255 ((state - value)/factor) * speedDelta); 256 } 257 } 258 else 259 { 260 // No decrease allowed for this group 261 netDelta = 0; 262 break; 263 } 264 } 265 catch (const std::out_of_range& oore) 266 { 267 // Property value not found, netDelta unchanged 268 } 269 } 270 // Update group's decrease allowed state 271 zone.setDecreaseAllow(&group, !(netDelta == 0)); 272 // Request speed decrease to occur on decrease interval 273 zone.requestSpeedDecrease(netDelta); 274 }; 275 } 276 277 } // namespace action 278 } // namespace control 279 } // namespace fan 280 } // namespace phosphor 281