Support speed decrease events
A net decrease speed action determines the net decrease delta from each
group member's property value and requests a speed decrease of that
delta from the current target speed.
From all the requests for a speed decrease on a zone, only the lowest
net decrease is used from all the groups subscribed to decrease a zone's
speed. The new target speed is only decreased when no increase requests
exist and the resulting target is above the zone's floor speed,
otherwise the floor speed is set as the new target.
Resolves openbmc/openbmc#1626
Change-Id: Iaefa7b25c3f44691dd3ca4084bfddd3c1a504de9
Signed-off-by: Matthew Barth <msbarth@us.ibm.com>
diff --git a/control/actions.hpp b/control/actions.hpp
index d4dedba..325cbbd 100644
--- a/control/actions.hpp
+++ b/control/actions.hpp
@@ -255,6 +255,58 @@
};
}
+/**
+ * @brief An action to set the speed decrease delta and request speed change
+ * @details Provides the ability to determine what the net decrease delta each
+ * zone's fan speeds should be updated by from their current target speed, and
+ * request that speed change occur on the next decrease interval.
+ *
+ * @param[in] state - State to compare the group's property value to
+ * @param[in] speedDelta - Speed delta of the group
+ *
+ * @return Lambda function
+ * A lambda function that determines the net decrease delta and requests
+ * a new target speed with that decrease for the zone.
+ */
+template <typename T>
+auto set_net_decrease_speed(T&& state, uint64_t speedDelta)
+{
+ return [speedDelta,
+ state = std::forward<T>(state)](auto& zone, auto& group)
+ {
+ auto netDelta = zone.getDecSpeedDelta();
+ std::for_each(
+ group.begin(),
+ group.end(),
+ [&zone, &state, &speedDelta, &netDelta](auto const& entry)
+ {
+ 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)
+ {
+ netDelta = (state - value) * speedDelta;
+ }
+ else
+ {
+ // Decrease is the difference times
+ // the given speed delta
+ netDelta = std::min(netDelta,
+ (state - value) * speedDelta);
+ }
+ }
+ }
+ );
+ // Request speed decrease to occur on decrease interval
+ zone.requestSpeedDecrease(netDelta);
+ };
+}
+
} // namespace action
} // namespace control
} // namespace fan
diff --git a/control/zone.cpp b/control/zone.cpp
index 5ed0c3a..1ca0b81 100644
--- a/control/zone.cpp
+++ b/control/zone.cpp
@@ -97,6 +97,7 @@
std::get<actionPos>(event)(*this,
std::get<groupPos>(event));
}
+ //TODO openbmc/openbmc#1625 Start timer for fan speed decreases
}
}
@@ -105,11 +106,6 @@
{
for (auto& fan : _fans)
{
- //TODO openbmc/openbmc#1626 Move to control algorithm function
- if (speed < _floorSpeed)
- {
- speed = _floorSpeed;
- }
fan->setSpeed(speed);
}
}
@@ -159,6 +155,35 @@
_incSpeedDelta = 0;
}
+void Zone::requestSpeedDecrease(uint64_t targetDelta)
+{
+ // Only decrease the lowest target delta requested
+ if (_decSpeedDelta == 0 || targetDelta < _decSpeedDelta)
+ {
+ _decSpeedDelta = targetDelta;
+ }
+
+ //TODO openbmc/openbmc#1625 Set decrease target speed when timer expires
+ // Only decrease speeds when no requested increases exist
+ if (_incSpeedDelta == 0)
+ {
+ // Target speed can not go below the defined floor speed
+ if ((_targetSpeed < _decSpeedDelta) ||
+ (_targetSpeed - _decSpeedDelta < _floorSpeed))
+ {
+ _targetSpeed = _floorSpeed;
+ }
+ else
+ {
+ _targetSpeed = _targetSpeed - _decSpeedDelta;
+ }
+ setSpeed(_targetSpeed);
+ }
+ // Clear decrease delta when timer expires
+ _decSpeedDelta = 0;
+ //TODO openbmc/openbmc#1625 Restart decrease timer
+}
+
void Zone::getProperty(sdbusplus::bus::bus& bus,
const std::string& path,
const std::string& iface,
diff --git a/control/zone.hpp b/control/zone.hpp
index cc05959..f445472 100644
--- a/control/zone.hpp
+++ b/control/zone.hpp
@@ -179,6 +179,16 @@
};
/**
+ * @brief Get the decrease speed delta
+ *
+ * @return - The current decrease speed delta
+ */
+ inline auto& getDecSpeedDelta() const
+ {
+ return _decSpeedDelta;
+ };
+
+ /**
* @brief Calculate the requested target speed from the given delta
* and increase the fan speeds, not going above the ceiling.
*
@@ -186,6 +196,14 @@
*/
void requestSpeedIncrease(uint64_t targetDelta);
+ /**
+ * @brief Calculate the requested target speed from the given delta
+ * and increase the fan speeds, not going above the ceiling.
+ *
+ * @param[in] targetDelta - The delta to increase the target speed by
+ */
+ void requestSpeedDecrease(uint64_t targetDelta);
+
private:
/**
@@ -244,6 +262,11 @@
uint64_t _incSpeedDelta = 0;
/**
+ * Speed decrease delta
+ */
+ uint64_t _decSpeedDelta = 0;
+
+ /**
* The vector of fans in this zone
*/
std::vector<std::unique_ptr<Fan>> _fans;