From 5cea18ba476c0cb6ea622be50a09ead00cd47b14 Mon Sep 17 00:00:00 2001 From: Ivan Li 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 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 #include #include +#include +#include +#include +#include +#include +#include +#include using namespace phosphor::logging; @@ -110,6 +117,12 @@ decltype(Thresholds::deassertHighSignal) Thresholds::deassertHighSignal = &CriticalObject::criticalHighAlarmDeasserted; +static std::unique_ptr cacheTimer = nullptr; +static std::unique_ptr powerMatch = nullptr; +static bool powerStatusOn = false; +static boost::asio::io_service io; +static auto conn = std::make_shared(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(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( + 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> + values; + message.read(objectName, values); + auto findState = values.find("CurrentHostState"); + if (findState != values.end()) + { + bool on = boost::ends_with( + std::get(findState->second), "Running"); + if (!on) + { + cacheTimer->stop(); + powerStatusOn = false; + return; + } + cacheTimer->start(std::chrono::duration_cast( + std::chrono::seconds(10))); + } + else { + powerStatusOn = false; + } + }); + + conn->async_method_call( + [](boost::system::error_code ec, + const std::variant& state) { + if (ec) + { + return; + } + powerStatusOn = + boost::ends_with(std::get(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::setLo)(lo); (*iface.*Thresholds::setHi)(hi); - auto alarmLowState = (*iface.*Thresholds::getAlarmLow)(); - auto alarmHighState = (*iface.*Thresholds::getAlarmHigh)(); (*iface.*Thresholds::alarmLo)(value <= lo); (*iface.*Thresholds::alarmHi)(value >= hi); - if (alarmLowState != (value <= lo)) - { - if (value <= lo) - { - (*iface.*Thresholds::assertLowSignal)(value); - } - else - { - (*iface.*Thresholds::deassertLowSignal)(value); - } - } - if (alarmHighState != (value >= hi)) - { - if (value >= hi) - { - (*iface.*Thresholds::assertHighSignal)(value); - } - else - { - (*iface.*Thresholds::deassertHighSignal)(value); - } - } auto type = Thresholds::type; obj[type] = iface; } -- 2.21.0