Decreases allowed based on all groups

For speed decreases to occur, all sensor groups involved with setting a
net decrease delta must be below their given t-control low values for
the associated zone. This handles the case where one or more sensor
groups' temperatures stabilize above their t-control low value, but one
or more other sensor groups' temperatures are below their t-control low
value which would result in speed decrease requests that could
eventually lead to fan speed oscillations.

Resolves openbmc/openbmc#2710

Change-Id: I382de5d3f9c3e631a332d49dfcb06e705ff6fc17
Signed-off-by: Matthew Barth <msbarth@us.ibm.com>
diff --git a/control/actions.hpp b/control/actions.hpp
index 55c8af8..c7356ab 100644
--- a/control/actions.hpp
+++ b/control/actions.hpp
@@ -230,41 +230,45 @@
             state = std::forward<T>(state)](auto& zone, auto& group)
     {
         auto netDelta = zone.getDecSpeedDelta();
-        std::for_each(
-            group.begin(),
-            group.end(),
-            [&zone, &state, &factor, &speedDelta, &netDelta](auto const& entry)
+        for (auto& entry : group)
+        {
+            try
             {
-                try
+                T value = zone.template getPropertyValue<T>(
+                        entry.first,
+                        std::get<intfPos>(entry.second),
+                        std::get<propPos>(entry.second));
+                // TODO openbmc/phosphor-fan-presence#7 - Support possible
+                // state types for comparison
+                if (value < state)
                 {
-                    T value = zone.template getPropertyValue<T>(
-                            entry.first,
-                            std::get<intfPos>(entry.second),
-                            std::get<propPos>(entry.second));
-                    // TODO openbmc/phosphor-fan-presence#7 - Support possible
-                    // state types for comparison
-                    if (value < state)
+                    if (netDelta == 0)
                     {
-                        if (netDelta == 0)
-                        {
-                            netDelta = ((state - value)/factor) * speedDelta;
-                        }
-                        else
-                        {
-                            // Decrease is the factor applied to the
-                            // difference times the given speed delta
-                            netDelta = std::min(
-                                netDelta,
-                                ((state - value)/factor) * speedDelta);
-                        }
+                        netDelta = ((state - value)/factor) * speedDelta;
+                    }
+                    else
+                    {
+                        // Decrease is the factor applied to the
+                        // difference times the given speed delta
+                        netDelta = std::min(
+                            netDelta,
+                            ((state - value)/factor) * speedDelta);
                     }
                 }
-                catch (const std::out_of_range& oore)
+                else
                 {
-                    // Property value not found, netDelta unchanged
+                    // No decrease allowed for this group
+                    netDelta = 0;
+                    break;
                 }
             }
-        );
+            catch (const std::out_of_range& oore)
+            {
+                // Property value not found, netDelta unchanged
+            }
+        }
+        // Update group's decrease allowed state
+        zone.setDecreaseAllow(&group, !(netDelta == 0));
         // Request speed decrease to occur on decrease interval
         zone.requestSpeedDecrease(netDelta);
     };