blob: a3718ea2a0947a999d2f626b8e17a6137c3d2811 [file] [log] [blame]
From 5cea18ba476c0cb6ea622be50a09ead00cd47b14 Mon Sep 17 00:00:00 2001
From: Ivan Li <rli11@lenovo.com>
Date: Wed, 25 Dec 2019 17:05:00 +0800
Subject: [PATCH] Add power on monitor mechanism
Summary:
1. Add "PWRONMON" attribute in sensor configuration file to determine whether it's power-on monitor sensor or not. (i.e. PWRONMON_temp1 = "ON")
2. Watching "CurrentHostState" property and then use it to turn on/off threshold alert for power-on monitor sensors.
Test Plan:
Check if there is any abnormal threshold events occurred in power off state or during power transition
Signed-off-by: Ivan Li <rli11@lenovo.com>
Change-Id: I76d3a664153141d94636e0011f3a48e4f6dee922
---
mainloop.cpp | 102 +++++++++++++++++++++++++++++++++++++++++++++++++
sensor.cpp | 11 +++++-
sensor.hpp | 13 +++++++
thresholds.hpp | 24 ------------
4 files changed, 125 insertions(+), 25 deletions(-)
diff --git a/mainloop.cpp b/mainloop.cpp
index 29dc26a..5e27a30 100644
--- a/mainloop.cpp
+++ b/mainloop.cpp
@@ -42,6 +42,13 @@
#include <string>
#include <unordered_set>
#include <xyz/openbmc_project/Sensor/Device/error.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/container/flat_map.hpp>
+#include <boost/algorithm/string/predicate.hpp>
+#include <sdbusplus/asio/connection.hpp>
+#include <sdbusplus/asio/object_server.hpp>
+#include <sdbusplus/message/types.hpp>
+#include <sdbusplus/timer.hpp>
using namespace phosphor::logging;
@@ -110,6 +117,12 @@ decltype(Thresholds<CriticalObject>::deassertHighSignal)
Thresholds<CriticalObject>::deassertHighSignal =
&CriticalObject::criticalHighAlarmDeasserted;
+static std::unique_ptr<phosphor::Timer> cacheTimer = nullptr;
+static std::unique_ptr<sdbusplus::bus::match::match> powerMatch = nullptr;
+static bool powerStatusOn = false;
+static boost::asio::io_service io;
+static auto conn = std::make_shared<sdbusplus::asio::connection>(io);
+
void updateSensorInterfaces(InterfaceMap& ifaces, SensorValueType value)
{
for (auto& iface : ifaces)
@@ -137,6 +150,83 @@ void updateSensorInterfaces(InterfaceMap& ifaces, SensorValueType value)
}
}
+void powerStatusSet()
+{
+ powerStatusOn = true;
+ return;
+}
+
+void createTimer()
+{
+ if (cacheTimer == nullptr)
+ {
+ cacheTimer = std::make_unique<phosphor::Timer>(powerStatusSet);
+ }
+}
+
+bool isPowerOn(void)
+{
+ if (!powerMatch)
+ {
+ throw std::runtime_error("Power Match Not Created");
+ }
+ return powerStatusOn;
+}
+
+void setupPowerMatch(sdbusplus::bus::bus& bus)
+{
+ if (powerMatch)
+ {
+ return;
+ }
+
+ powerMatch = std::make_unique<sdbusplus::bus::match::match>(
+ bus,
+ "type='signal',interface='org.freedesktop.DBus.Properties',path='/xyz/"
+ "openbmc_project/state/"
+ "host0',arg0='xyz.openbmc_project.State.Host'",
+ [](sdbusplus::message::message& message) {
+ std::string objectName;
+ boost::container::flat_map<std::string, std::variant<std::string>>
+ values;
+ message.read(objectName, values);
+ auto findState = values.find("CurrentHostState");
+ if (findState != values.end())
+ {
+ bool on = boost::ends_with(
+ std::get<std::string>(findState->second), "Running");
+ if (!on)
+ {
+ cacheTimer->stop();
+ powerStatusOn = false;
+ return;
+ }
+ cacheTimer->start(std::chrono::duration_cast<std::chrono::microseconds>(
+ std::chrono::seconds(10)));
+ }
+ else {
+ powerStatusOn = false;
+ }
+ });
+
+ conn->async_method_call(
+ [](boost::system::error_code ec,
+ const std::variant<std::string>& state) {
+ if (ec)
+ {
+ return;
+ }
+ powerStatusOn =
+ boost::ends_with(std::get<std::string>(state), "Running");
+ },
+ "xyz.openbmc_project.State.Host",
+ "/xyz/openbmc_project/state/host0",
+ "org.freedesktop.DBus.Properties", "Get",
+ "xyz.openbmc_project.State.Host", "CurrentHostState");
+
+ createTimer();
+}
+
std::string MainLoop::getID(SensorSet::container_t::const_reference sensor)
{
std::string id;
@@ -418,6 +508,7 @@ void MainLoop::init()
_interval = std::strtoull(interval.c_str(), NULL, 10);
}
}
+ setupPowerMatch(_bus);
}
void MainLoop::read()
@@ -462,6 +553,12 @@ void MainLoop::read()
try
{
+ if(sensor->pwrOnMonitor() && !isPowerOn())
+ {
+ statusIface->functional(false);
+ continue;
+ }
+
if (sensor->hasFaultFile())
{
auto fault = _ioAccess->read(sensorSysfsType, sensorSysfsNum,
@@ -588,6 +685,11 @@ void MainLoop::read()
}
}
+ if(sensor->pwrOnMonitor() && !isPowerOn())
+ {
+ statusIface->functional(false);
+ continue;
+ }
updateSensorInterfaces(obj, value);
}
catch (const std::system_error& e)
diff --git a/sensor.cpp b/sensor.cpp
index ac2f896..72b45f8 100644
--- a/sensor.cpp
+++ b/sensor.cpp
@@ -32,7 +32,7 @@ Sensor::Sensor(const SensorSet::key_type& sensor,
const hwmonio::HwmonIOInterface* ioAccess,
const std::string& devPath) :
_sensor(sensor),
- _ioAccess(ioAccess), _devPath(devPath), _scale(0), _hasFaultFile(false)
+ _ioAccess(ioAccess), _devPath(devPath), _scale(0), _hasFaultFile(false), _pwrOnMonitor(false)
{
auto chip = env::getEnv("GPIOCHIP", sensor);
auto access = env::getEnv("GPIO", sensor);
@@ -61,6 +61,15 @@ Sensor::Sensor(const SensorSet::key_type& sensor,
auto senRmRCs = env::getEnv("REMOVERCS", sensor);
// Add sensor removal return codes defined per sensor
addRemoveRCs(senRmRCs);
+
+ auto pwrOnMon = env::getEnv("PWRONMON", sensor);
+ if (!pwrOnMon.empty())
+ {
+ if (pwrOnMon == "ON")
+ {
+ _pwrOnMonitor = true;
+ }
+ }
}
void Sensor::addRemoveRCs(const std::string& rcList)
diff --git a/sensor.hpp b/sensor.hpp
index 64d6e48..41c0fe7 100644
--- a/sensor.hpp
+++ b/sensor.hpp
@@ -151,6 +151,16 @@ class Sensor
return _hasFaultFile;
}
+ /**
+ * @brief Get whether the sensor only need to be monitored in power on state or not.
+ *
+ * @return - Boolean on whether the sensor only need to be monitored in power on state
+ */
+ inline bool pwrOnMonitor(void) const
+ {
+ return _pwrOnMonitor;
+ }
+
private:
/** @brief Sensor object's identifiers */
SensorSet::key_type _sensor;
@@ -172,6 +182,9 @@ class Sensor
/** @brief Tracks whether the sensor has a fault file or not. */
bool _hasFaultFile;
+
+ /** @brief Whether the sensor only need to be monitored in power on state or not. */
+ bool _pwrOnMonitor;
};
/**
diff --git a/thresholds.hpp b/thresholds.hpp
index 8d557fc..0ffe0ce 100644
--- a/thresholds.hpp
+++ b/thresholds.hpp
@@ -137,32 +137,8 @@ auto addThreshold(const std::string& sensorType, const std::string& sensorID,
auto hi = stod(tHi) * std::pow(10, scale);
(*iface.*Thresholds<T>::setLo)(lo);
(*iface.*Thresholds<T>::setHi)(hi);
- auto alarmLowState = (*iface.*Thresholds<T>::getAlarmLow)();
- auto alarmHighState = (*iface.*Thresholds<T>::getAlarmHigh)();
(*iface.*Thresholds<T>::alarmLo)(value <= lo);
(*iface.*Thresholds<T>::alarmHi)(value >= hi);
- if (alarmLowState != (value <= lo))
- {
- if (value <= lo)
- {
- (*iface.*Thresholds<T>::assertLowSignal)(value);
- }
- else
- {
- (*iface.*Thresholds<T>::deassertLowSignal)(value);
- }
- }
- if (alarmHighState != (value >= hi))
- {
- if (value >= hi)
- {
- (*iface.*Thresholds<T>::assertHighSignal)(value);
- }
- else
- {
- (*iface.*Thresholds<T>::deassertHighSignal)(value);
- }
- }
auto type = Thresholds<T>::type;
obj[type] = iface;
}
--
2.21.0