Filter ADC threshold crossings
When power goes down we get bad events because the
voltage rail spins down faster than pgood. Add in
a delay to check power 2 seconds after the event to
make sure power isn't going down.
Tested-by: power cycled and extra SEL went away
Change-Id: Ib820ccb50d1a949b8096f08e2711ad7a7c36087b
Signed-off-by: James Feist <james.feist@linux.intel.com>
diff --git a/include/ADCSensor.hpp b/include/ADCSensor.hpp
index fd248da..fbb256b 100644
--- a/include/ADCSensor.hpp
+++ b/include/ADCSensor.hpp
@@ -24,6 +24,7 @@
int errCount;
double scaleFactor;
PowerState readState;
+ thresholds::ThresholdTimer thresholdTimer;
void setupRead(void);
void handleResponse(const boost::system::error_code& err);
void checkThresholds(void) override;
diff --git a/include/Thresholds.hpp b/include/Thresholds.hpp
index 22943c9..16b8bb9 100644
--- a/include/Thresholds.hpp
+++ b/include/Thresholds.hpp
@@ -1,5 +1,6 @@
#pragma once
#include <Utils.hpp>
+#include <boost/asio/io_service.hpp>
#include <nlohmann/json.hpp>
struct Sensor;
@@ -27,7 +28,6 @@
Direction direction;
double value;
bool writeable;
- bool asserted = false;
bool operator==(const Threshold& rhs) const
{
@@ -36,6 +36,67 @@
}
};
+void assertThresholds(Sensor* sensor, thresholds::Level level,
+ thresholds::Direction direction, bool assert);
+
+struct ThresholdTimer
+{
+
+ ThresholdTimer(boost::asio::io_service& io, Sensor* sensor) :
+ criticalTimer(io), warningTimer(io), sensor(sensor)
+ {
+ }
+
+ void startTimer(const Threshold& threshold)
+ {
+ constexpr const size_t waitTime = 2;
+
+ if (threshold.level == WARNING && !warningRunning)
+ {
+ warningRunning = true;
+ warningTimer.expires_from_now(boost::posix_time::seconds(waitTime));
+ warningTimer.async_wait(
+ [this, threshold](boost::system::error_code ec) {
+ if (ec == boost::asio::error::operation_aborted)
+ {
+ return; // we're being canceled
+ }
+ if (isPowerOn())
+ {
+ assertThresholds(sensor, threshold.level,
+ threshold.direction, true);
+ }
+ warningRunning = false;
+ });
+ }
+ else if (threshold.level == CRITICAL && !criticalRunning)
+ {
+ criticalRunning = true;
+ criticalTimer.expires_from_now(
+ boost::posix_time::seconds(waitTime));
+ criticalTimer.async_wait(
+ [this, threshold](boost::system::error_code ec) {
+ if (ec == boost::asio::error::operation_aborted)
+ {
+ return; // we're being canceled
+ }
+ if (isPowerOn())
+ {
+ assertThresholds(sensor, threshold.level,
+ threshold.direction, true);
+ }
+ criticalRunning = false;
+ });
+ }
+ }
+
+ boost::asio::deadline_timer criticalTimer;
+ boost::asio::deadline_timer warningTimer;
+ bool criticalRunning = false;
+ bool warningRunning = false;
+ Sensor* sensor;
+};
+
bool parseThresholdsFromConfig(
const SensorData& sensorData,
std::vector<thresholds::Threshold>& thresholdVector,
@@ -58,6 +119,5 @@
void updateThresholds(Sensor* sensor);
// returns false if a critical threshold has been crossed, true otherwise
bool checkThresholds(Sensor* sensor);
-void assertThresholds(Sensor* sensor, thresholds::Level level,
- thresholds::Direction direction, bool assert);
+void checkThresholdsPowerDelay(Sensor* sensor, ThresholdTimer& thresholdTimer);
} // namespace thresholds
diff --git a/src/ADCSensor.cpp b/src/ADCSensor.cpp
index e06c8dd..01edc13 100644
--- a/src/ADCSensor.cpp
+++ b/src/ADCSensor.cpp
@@ -48,7 +48,7 @@
"xyz.openbmc_project.Configuration.ADC", maxReading, minReading),
objServer(objectServer), scaleFactor(scaleFactor),
readState(std::move(readState)), inputDev(io, open(path.c_str(), O_RDONLY)),
- waitTimer(io), errCount(0)
+ waitTimer(io), errCount(0), thresholdTimer(io, this)
{
sensorInterface = objectServer.add_interface(
"/xyz/openbmc_project/sensors/voltage/" + name,
@@ -168,5 +168,6 @@
{
return;
}
- thresholds::checkThresholds(this);
+
+ thresholds::checkThresholdsPowerDelay(this, thresholdTimer);
}
diff --git a/src/Thresholds.cpp b/src/Thresholds.cpp
index 4932bce..653b4e6 100644
--- a/src/Thresholds.cpp
+++ b/src/Thresholds.cpp
@@ -208,59 +208,80 @@
}
}
-bool checkThresholds(Sensor* sensor)
+static std::vector<std::pair<Threshold, bool>> checkThresholds(Sensor* sensor,
+ double value)
{
- bool status = true;
-
+ std::vector<std::pair<Threshold, bool>> thresholdChanges;
if (sensor->thresholds.empty())
{
- return true;
+ return thresholdChanges;
}
+
for (auto& threshold : sensor->thresholds)
{
- if (std::isnan(sensor->value))
+ if (threshold.direction == thresholds::Direction::HIGH)
{
- threshold.asserted = false;
- }
- else if (threshold.direction == thresholds::Direction::HIGH)
- {
- if (sensor->value > threshold.value && !threshold.asserted)
+ if (value > threshold.value)
{
- assertThresholds(sensor, threshold.level, threshold.direction,
- true);
- threshold.asserted = true;
+ thresholdChanges.push_back(std::make_pair(threshold, true));
}
- else if (sensor->value <= threshold.value && threshold.asserted)
+ else if (value <= threshold.value)
{
- assertThresholds(sensor, threshold.level, threshold.direction,
- false);
- threshold.asserted = false;
+ thresholdChanges.push_back(std::make_pair(threshold, false));
}
}
else
{
- if (sensor->value < threshold.value && !threshold.asserted)
+ if (value < threshold.value)
{
- assertThresholds(sensor, threshold.level, threshold.direction,
- true);
- threshold.asserted = true;
+ thresholdChanges.push_back(std::make_pair(threshold, true));
}
- else if (sensor->value >= threshold.value && threshold.asserted)
+ else if (value >= threshold.value)
{
- assertThresholds(sensor, threshold.level, threshold.direction,
- false);
- threshold.asserted = false;
+ thresholdChanges.push_back(std::make_pair(threshold, false));
}
}
- if (threshold.level == thresholds::Level::CRITICAL &&
- threshold.asserted)
- {
- status = false;
- }
}
+ return thresholdChanges;
+}
+
+bool checkThresholds(Sensor* sensor)
+{
+ bool status = false;
+ std::vector<std::pair<Threshold, bool>> changes =
+ checkThresholds(sensor, sensor->value);
+ for (const auto& [threshold, asserted] : changes)
+ {
+ assertThresholds(sensor, threshold.level, threshold.direction,
+ asserted);
+ if (threshold.level == thresholds::Level::CRITICAL && asserted)
+ {
+ status = true;
+ }
+ }
+
return status;
}
+void checkThresholdsPowerDelay(Sensor* sensor, ThresholdTimer& thresholdTimer)
+{
+
+ std::vector<std::pair<Threshold, bool>> changes =
+ checkThresholds(sensor, sensor->value);
+ for (const auto& [threshold, asserted] : changes)
+ {
+ if (asserted)
+ {
+ thresholdTimer.startTimer(threshold);
+ }
+ else
+ {
+ assertThresholds(sensor, threshold.level, threshold.direction,
+ false);
+ }
+ }
+}
+
void assertThresholds(Sensor* sensor, thresholds::Level level,
thresholds::Direction direction, bool assert)
{