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 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 */ 28 void set_request_speed_base_with_max(Zone& zone, const Group& group); 29 30 /** 31 * @brief An action to set the speed on a zone 32 * @details The zone is held at the given speed when a defined number of 33 * 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 */ 43 template <typename T> 44 auto count_state_before_speed(size_t count, T&& state, uint64_t speed) 45 { 46 return [count, 47 speed, 48 state = std::forward<T>(state)](auto& zone, auto& group) 49 { 50 size_t numAtState = std::count_if( 51 group.begin(), 52 group.end(), 53 [&zone, &state](auto const& entry) 54 { 55 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 } 67 }); 68 if (numAtState >= count) 69 { 70 zone.setSpeed(speed); 71 } 72 // Update group's fan control active allowed based on action results 73 zone.setActiveAllow(&group, !(numAtState >= count)); 74 }; 75 } 76 77 /** 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 * 85 * @return Action lambda function 86 * An Action function to set the zone's floor speed when the average of 87 * property values within the group is below the lowest sensor value given 88 */ 89 Action set_floor_from_average_sensor_value( 90 std::map<int64_t, uint64_t>&& val_to_speed); 91 92 /** 93 * @brief An action to set the ceiling speed on a zone 94 * @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. 98 * 99 * @param[in] val_to_speed - Ordered map of sensor value-to-speed transitions 100 * 101 * @return Action lambda function 102 * An Action function to set the zone's ceiling speed when the average of 103 * property values within the group is above(increasing) or 104 * below(decreasing) the key transition point 105 */ 106 Action set_ceiling_from_average_sensor_value( 107 std::map<int64_t, uint64_t>&& val_to_speed); 108 109 /** 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 116 * @param[in] factor - Factor to apply to the calculated net delta 117 * @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 */ 123 template <typename T> 124 auto set_net_increase_speed(T&& state, T&& factor, uint64_t speedDelta) 125 { 126 return [speedDelta, 127 factor = std::forward<T>(factor), 128 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(), 134 [&zone, &state, &factor, &speedDelta, &netDelta]( 135 auto const& entry) 136 { 137 try 138 { 139 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 { 147 // Increase by at least a single delta(factor) 148 // to attempt bringing under 'state' 149 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); 157 } 158 } 159 catch (const std::out_of_range& oore) 160 { 161 // Property value not found, netDelta unchanged 162 } 163 } 164 ); 165 // Request speed change for target speed update 166 zone.requestSpeedIncrease(netDelta); 167 }; 168 } 169 170 /** 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 177 * @param[in] factor - Factor to apply to the calculated net delta 178 * @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 */ 184 template <typename T> 185 auto set_net_decrease_speed(T&& state, T&& factor, uint64_t speedDelta) 186 { 187 return [speedDelta, 188 factor = std::forward<T>(factor), 189 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(), 195 [&zone, &state, &factor, &speedDelta, &netDelta](auto const& entry) 196 { 197 try 198 { 199 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) 206 { 207 if (netDelta == 0) 208 { 209 netDelta = ((state - value)/factor) * speedDelta; 210 } 211 else 212 { 213 // 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); 218 } 219 } 220 } 221 catch (const std::out_of_range& oore) 222 { 223 // Property value not found, netDelta unchanged 224 } 225 } 226 ); 227 // Request speed decrease to occur on decrease interval 228 zone.requestSpeedDecrease(netDelta); 229 }; 230 } 231 232 } // namespace action 233 } // namespace control 234 } // namespace fan 235 } // namespace phosphor 236