summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-phosphor/sensors
diff options
context:
space:
mode:
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-phosphor/sensors')
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors/0001-Add-check-for-min-max-received-from-hwmon-files.patch108
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors/0002-Fix-PECI-client-creation-flow.patch159
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors/0003-Fix-missing-threshold-de-assert-event-when-threshold.patch139
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors/0004-Fan-Tach-Sensor-Threshold-Ignore-Zero.patch58
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors/0005-Fix-PECI-ioctl-number.patch29
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors/0006-CPUSensor-create-RequirediTempSensor-if-defined.patch234
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors/intrusionsensor-depend-on-networkd.conf3
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors_%.bbappend43
8 files changed, 773 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors/0001-Add-check-for-min-max-received-from-hwmon-files.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors/0001-Add-check-for-min-max-received-from-hwmon-files.patch
new file mode 100644
index 000000000..33d35ec5e
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors/0001-Add-check-for-min-max-received-from-hwmon-files.patch
@@ -0,0 +1,108 @@
+From 2516d67f8bb5ecd241b8dcdec3f8c58d0e3c4744 Mon Sep 17 00:00:00 2001
+From: Wojciech Dembinski <wojciech.dembinski@intel.com>
+Date: Mon, 7 Dec 2020 19:23:10 +0100
+Subject: [PATCH] Add check for min/max received from hwmon files
+
+When hwmon reports incorrect min/max values or CPU Sensor cannot access
+readings, it shall keep the last known good readings and not update
+DBus with incorrect values.
+This patch adds min < max verification check for the values received
+from hwmon and removes check for power on/off in the case of a read
+failure.
+
+Tested manually on a physical platform, test cases cover incorrect
+max/min values and failing access to hwmon files.
+SDR over IPMI can be fully received in the case of error.
+
+Signed-off-by: Wojciech Dembinski <wojciech.dembinski@intel.com>
+Change-Id: Ia061f849b0f434812f822ed1902c8964d4c64b45
+---
+ src/CPUSensor.cpp | 50 ++++++++++++++++++++++++-----------------------
+ 1 file changed, 26 insertions(+), 24 deletions(-)
+
+diff --git a/src/CPUSensor.cpp b/src/CPUSensor.cpp
+index 2356821..01f5eb6 100644
+--- a/src/CPUSensor.cpp
++++ b/src/CPUSensor.cpp
+@@ -1,5 +1,5 @@
+ /*
+-// Copyright (c) 2018 Intel Corporation
++// Copyright (c) 2018-2021 Intel Corporation
+ //
+ // Licensed under the Apache License, Version 2.0 (the "License");
+ // you may not use this file except in compliance with the License.
+@@ -146,19 +146,22 @@ void CPUSensor::setupRead(void)
+
+ void CPUSensor::updateMinMaxValues(void)
+ {
++ double newMin = std::numeric_limits<double>::quiet_NaN();
++ double newMax = std::numeric_limits<double>::quiet_NaN();
++
+ const boost::container::flat_map<
+ std::string,
+ std::vector<std::tuple<const char*, std::reference_wrapper<double>,
+- const char*>>>
+- map = {
++ const char*, std::reference_wrapper<double>>>>
++ map = {
++ {
++ "cap",
+ {
+- "cap",
+- {
+- std::make_tuple("cap_max", std::ref(maxValue), "MaxValue"),
+- std::make_tuple("cap_min", std::ref(minValue), "MinValue"),
+- },
++ std::make_tuple("cap_max", std::ref(maxValue), "MaxValue", std::ref(newMax)),
++ std::make_tuple("cap_min", std::ref(minValue), "MinValue", std::ref(newMin)),
+ },
+- };
++ },
++ };
+
+ if (auto fileParts = splitFileName(path))
+ {
+@@ -168,26 +171,25 @@ void CPUSensor::updateMinMaxValues(void)
+ {
+ for (const auto& vectorItem : mapIt->second)
+ {
+- auto& [suffix, oldValue, dbusName] = vectorItem;
++ auto& [suffix, oldValue, dbusName, newValue] = vectorItem;
+ auto attrPath = boost::replace_all_copy(path, fileItem, suffix);
+- if (auto newVal =
+- readFile(attrPath, CPUSensor::sensorScaleFactor))
++
++ if(auto tmp = readFile(attrPath, CPUSensor::sensorScaleFactor))
+ {
+- updateProperty(sensorInterface, oldValue, *newVal,
+- dbusName);
++ newValue.get() = *tmp;
+ }
+ else
+ {
+- if (isPowerOn())
+- {
+- updateProperty(sensorInterface, oldValue, 0, dbusName);
+- }
+- else
+- {
+- updateProperty(sensorInterface, oldValue,
+- std::numeric_limits<double>::quiet_NaN(),
+- dbusName);
+- }
++ newValue.get() = std::numeric_limits<double>::quiet_NaN();
++ }
++ }
++
++ if(std::isfinite(newMin) && std::isfinite(newMax) && (newMin < newMax))
++ {
++ for (const auto& vectorItem : mapIt->second)
++ {
++ auto& [suffix, oldValue, dbusName, newValue] = vectorItem;
++ updateProperty(sensorInterface, oldValue, newValue, dbusName);
+ }
+ }
+ }
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors/0002-Fix-PECI-client-creation-flow.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors/0002-Fix-PECI-client-creation-flow.patch
new file mode 100644
index 000000000..cfdc99d66
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors/0002-Fix-PECI-client-creation-flow.patch
@@ -0,0 +1,159 @@
+From 0a1b2a13f6dbc64b5851ac2b1ca99d57afa78d60 Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Wed, 27 Jan 2021 15:52:16 -0800
+Subject: [PATCH] Fix PECI client creation flow
+
+This commit fixes the PECI client creation flow to make it retry
+the creation when the client is not exposed correctly.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ src/CPUSensorMain.cpp | 66 +++++++++++++++++++++++++++++++++++--------
+ 1 file changed, 54 insertions(+), 12 deletions(-)
+
+diff --git a/src/CPUSensorMain.cpp b/src/CPUSensorMain.cpp
+index f304e3f..92c1716 100644
+--- a/src/CPUSensorMain.cpp
++++ b/src/CPUSensorMain.cpp
+@@ -82,6 +82,7 @@ struct CPUConfig
+ };
+
+ static constexpr const char* peciDev = "/dev/peci-";
++static constexpr const char* peciDevPath = "/sys/bus/peci/devices/";
+ static constexpr const unsigned int rankNumMax = 8;
+
+ namespace fs = std::filesystem;
+@@ -167,7 +168,7 @@ bool createSensors(boost::asio::io_service& io,
+ }
+
+ std::vector<fs::path> hwmonNamePaths;
+- if (!findFiles(fs::path(R"(/sys/bus/peci/devices)"),
++ if (!findFiles(fs::path(peciDevPath),
+ R"(peci-\d+/\d+-.+/peci-.+/hwmon/hwmon\d+/name$)",
+ hwmonNamePaths, 6))
+ {
+@@ -403,7 +404,7 @@ bool createSensors(boost::asio::io_service& io,
+ return true;
+ }
+
+-void exportDevice(const CPUConfig& config)
++int exportDevice(const CPUConfig& config)
+ {
+ std::ostringstream hex;
+ hex << std::hex << config.addr;
+@@ -411,9 +412,12 @@ void exportDevice(const CPUConfig& config)
+ std::string busStr = std::to_string(config.bus);
+
+ std::string parameters = "peci-client 0x" + addrHexStr;
+- std::string device = "/sys/bus/peci/devices/peci-" + busStr + "/new_device";
++ std::string devPath = peciDevPath;
++ std::string delDevice = devPath + "peci-" + busStr + "/delete_device";
++ std::string newDevice = devPath + "peci-" + busStr + "/new_device";
++ std::string newClient = devPath + busStr + "-" + addrHexStr + "/driver";
+
+- std::filesystem::path devicePath(device);
++ std::filesystem::path devicePath(newDevice);
+ const std::string& dir = devicePath.parent_path().string();
+ for (const auto& path : std::filesystem::directory_iterator(dir))
+ {
+@@ -431,20 +435,38 @@ void exportDevice(const CPUConfig& config)
+ std::cout << parameters << " on bus " << busStr
+ << " is already exported\n";
+ }
+- return;
++
++ std::ofstream delDeviceFile(delDevice);
++ if (!delDeviceFile.good())
++ {
++ std::cerr << "Error opening " << delDevice << "\n";
++ return -1;
++ }
++ delDeviceFile << parameters;
++ delDeviceFile.close();
++
++ break;
+ }
+ }
+
+- std::ofstream deviceFile(device);
++ std::ofstream deviceFile(newDevice);
+ if (!deviceFile.good())
+ {
+- std::cerr << "Error writing " << device << "\n";
+- return;
++ std::cerr << "Error opening " << newDevice << "\n";
++ return -1;
+ }
+ deviceFile << parameters;
+ deviceFile.close();
+
++ if (!std::filesystem::exists(newClient))
++ {
++ std::cerr << "Error creating " << newClient << "\n";
++ return -1;
++ }
++
+ std::cout << parameters << " on bus " << busStr << " is exported\n";
++
++ return 0;
+ }
+
+ void detectCpu(boost::asio::deadline_timer& pingTimer,
+@@ -460,6 +482,11 @@ void detectCpu(boost::asio::deadline_timer& pingTimer,
+
+ for (CPUConfig& config : cpuConfigs)
+ {
++ if (config.state == State::READY)
++ {
++ continue;
++ }
++
+ std::string peciDevPath = peciDev + std::to_string(config.bus);
+ auto file = open(peciDevPath.c_str(), O_RDWR | O_CLOEXEC);
+ if (file < 0)
+@@ -510,16 +537,29 @@ void detectCpu(boost::asio::deadline_timer& pingTimer,
+ newState = State::OFF;
+ }
+
+- close(file);
+-
+ if (config.state != newState)
+ {
+ if (newState != State::OFF)
+ {
+ if (config.state == State::OFF)
+ {
+- std::cout << config.name << " is detected\n";
+- exportDevice(config);
++ struct peci_rd_pkg_cfg_msg msg;
++ msg.addr = config.addr;
++ msg.index = PECI_MBX_INDEX_CPU_ID;
++ msg.param = 0;
++ msg.rx_len = 4;
++ if (!ioctl(file, PECI_IOC_RD_PKG_CFG, &msg))
++ {
++ std::cout << config.name << " is detected\n";
++ if (exportDevice(config))
++ {
++ newState = State::OFF;
++ }
++ }
++ else
++ {
++ newState = State::OFF;
++ }
+ }
+
+ if (newState == State::ON)
+@@ -542,6 +582,8 @@ void detectCpu(boost::asio::deadline_timer& pingTimer,
+ keepPinging = true;
+ }
+
++ close(file);
++
+ if (debug)
+ {
+ std::cout << config.name << ", state: " << config.state << "\n";
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors/0003-Fix-missing-threshold-de-assert-event-when-threshold.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors/0003-Fix-missing-threshold-de-assert-event-when-threshold.patch
new file mode 100644
index 000000000..c9175fd64
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors/0003-Fix-missing-threshold-de-assert-event-when-threshold.patch
@@ -0,0 +1,139 @@
+From 17e3ed85f2ff919ff52b4a3fe7a1eb0026f28898 Mon Sep 17 00:00:00 2001
+From: Zhikui Ren <zhikui.ren@intel.com>
+Date: Thu, 24 Sep 2020 14:27:32 -0700
+Subject: [PATCH] Fix missing threshold de-assert event when threshold changes.
+
+Sensor can be re-constructed when sensor configuration changes
+like a new threshold value. Threshold deassert can be missed
+if the new threshold value fixes the alarm because the
+default state for new threshold interface is de-asserted.
+Send threshold de-assert message after interfaces are initialized to
+ensure de-assert event is logged if there is an active assert
+event.
+
+Tested:
+step1:
+busctl set-property xyz.openbmc_project.ADCSensor /xyz/openbmc_project/sensors/voltage/P3VBAT xyz.openbmc_project.Sensor.Threshold.Warning WarningLow d 2.457
+ipmitool sel list
+SEL has no entries
+step2:
+busctl set-property xyz.openbmc_project.ADCSensor /xyz/openbmc_project/sensors/voltage/P3VBAT xyz.openbmc_project.Sensor.Threshold.Warning WarningLow d 3.1
+ipmitool sel list
+ 1 | 09/24/20 | 21:30:15 UTC | Voltage #0x2d | Lower Non-critical going low | Asserted
+step3:
+busctl set-property xyz.openbmc_project.ADCSensor /xyz/openbmc_project/sensors/voltage/P3VBAT xyz.openbmc_project.Sensor.Threshold.Warning WarningLow d 2.457
+ipmitool sel list
+ 1 | 09/24/20 | 21:30:15 UTC | Voltage #0x2d | Lower Non-critical going low | Asserted
+ 2 | 09/24/20 | 21:30:33 UTC | Voltage #0x2d | Lower Non-critical going low | Deasserted
+
+Signed-off-by: Zhikui Ren <zhikui.ren@intel.com>
+Change-Id: If28870ac1e0d09be4a631a3145408ec70390dfc5
+---
+ include/Thresholds.hpp | 5 ++++-
+ include/sensor.hpp | 13 +++++++++++++
+ src/ADCSensor.cpp | 1 +
+ src/Thresholds.cpp | 15 +++++++++++++--
+ 4 files changed, 31 insertions(+), 3 deletions(-)
+
+diff --git a/include/Thresholds.hpp b/include/Thresholds.hpp
+index ca2b0a0..c1d0baf 100644
+--- a/include/Thresholds.hpp
++++ b/include/Thresholds.hpp
+@@ -45,7 +45,10 @@ struct Threshold
+
+ void assertThresholds(Sensor* sensor, double assertValue,
+ thresholds::Level level, thresholds::Direction direction,
+- bool assert);
++ bool assert, bool force = false);
++
++void forceDeassertThresholds(Sensor* sensor, thresholds::Level level,
++ thresholds::Direction direction);
+
+ struct TimerUsed
+ {
+diff --git a/include/sensor.hpp b/include/sensor.hpp
+index 0ef87d5..d50b2ff 100644
+--- a/include/sensor.hpp
++++ b/include/sensor.hpp
+@@ -312,6 +312,19 @@ struct Sensor
+ operationalInterface->register_property("Functional", true);
+ operationalInterface->initialize();
+ }
++
++ // Sensor can be reconstructed when sensor configuration changes
++ // like a new threshold value. Threshold deassert can be missed
++ // if the new threshold value fixes the alarm because
++ // default state for new threshold interface is de-asserted.
++ // Send threshold de-assert message during initialization to
++ // ensure de-assert events are logged if there is an active assert
++ // event.
++ for (auto& threshold : thresholds)
++ {
++ thresholds::forceDeassertThresholds(this, threshold.level,
++ threshold.direction);
++ }
+ }
+
+ bool readingStateGood()
+diff --git a/src/ADCSensor.cpp b/src/ADCSensor.cpp
+index fe600d7..632fc8c 100644
+--- a/src/ADCSensor.cpp
++++ b/src/ADCSensor.cpp
+@@ -88,6 +88,7 @@ ADCSensor::~ADCSensor()
+ // close the input dev to cancel async operations
+ inputDev.close();
+ waitTimer.cancel();
++
+ objServer.remove_interface(thresholdInterfaceWarning);
+ objServer.remove_interface(thresholdInterfaceCritical);
+ objServer.remove_interface(sensorInterface);
+diff --git a/src/Thresholds.cpp b/src/Thresholds.cpp
+index f4d4ed0..3c791c9 100644
+--- a/src/Thresholds.cpp
++++ b/src/Thresholds.cpp
+@@ -344,6 +344,7 @@ bool checkThresholds(Sensor* sensor)
+ {
+ bool status = true;
+ std::vector<ChangeParam> changes = checkThresholds(sensor, sensor->value);
++
+ for (const auto& change : changes)
+ {
+ assertThresholds(sensor, change.assertValue, change.threshold.level,
+@@ -392,7 +393,7 @@ void checkThresholdsPowerDelay(Sensor* sensor, ThresholdTimer& thresholdTimer)
+
+ void assertThresholds(Sensor* sensor, double assertValue,
+ thresholds::Level level, thresholds::Direction direction,
+- bool assert)
++ bool assert, bool force)
+ {
+ std::string property;
+ std::shared_ptr<sdbusplus::asio::dbus_interface> interface;
+@@ -432,7 +433,9 @@ void assertThresholds(Sensor* sensor, double assertValue,
+ return;
+ }
+
+- if (interface->set_property<bool, true>(property, assert))
++ bool propertyChanged =
++ interface->set_property<bool, true>(property, assert);
++ if (force || propertyChanged)
+ {
+ try
+ {
+@@ -452,6 +455,14 @@ void assertThresholds(Sensor* sensor, double assertValue,
+ }
+ }
+
++// Explicitely de-assert a threshold with existing sensor value
++// Should only be called on sensor desctruction
++void forceDeassertThresholds(Sensor* sensor, thresholds::Level level,
++ thresholds::Direction direction)
++{
++ assertThresholds(sensor, sensor->value, level, direction, false, true);
++}
++
+ bool parseThresholdsFromAttr(
+ std::vector<thresholds::Threshold>& thresholdVector,
+ const std::string& inputPath, const double& scaleFactor,
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors/0004-Fan-Tach-Sensor-Threshold-Ignore-Zero.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors/0004-Fan-Tach-Sensor-Threshold-Ignore-Zero.patch
new file mode 100644
index 000000000..65558aba5
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors/0004-Fan-Tach-Sensor-Threshold-Ignore-Zero.patch
@@ -0,0 +1,58 @@
+From 8f850ea8745aa7aafcb504aa50686ba00fdfcfee Mon Sep 17 00:00:00 2001
+From: Zhikui Ren <zhikui.ren@intel.com>
+Date: Fri, 19 Feb 2021 12:14:05 -0800
+Subject: [PATCH] Fan Tach Sensor Threshold Ignore Zero
+
+Currently there are systems that have system fans plugged
+into different fan connectors. Fan present detection is
+not supported in most of these systems. Critical low
+threshold is asserted for the non-utilized fans
+resulting in FSC boost all fans.
+
+Skip threshold checking for fan tach reading less or equal
+to zero. This is a temporary WA until a more robust solution
+is available.
+
+Note: with this workaround a completely non-working fan
+will not be detected. FSC will still boost fans due to other
+constraints if the system can't be cooled with the working fans.
+
+Tested:
+No cr event for the missing fans.
+
+Signed-off-by: Zhikui Ren <zhikui.ren@intel.com>
+---
+ src/TachSensor.cpp | 16 +++++++++++-----
+ 1 file changed, 11 insertions(+), 5 deletions(-)
+
+diff --git a/src/TachSensor.cpp b/src/TachSensor.cpp
+index 1ec979f..b17be98 100644
+--- a/src/TachSensor.cpp
++++ b/src/TachSensor.cpp
+@@ -185,12 +185,18 @@ void TachSensor::handleResponse(const boost::system::error_code& err)
+
+ void TachSensor::checkThresholds(void)
+ {
+- bool status = thresholds::checkThresholds(this);
+-
+- if (redundancy && *redundancy)
++ // WA - treat value <= 0 as not present
++ bool status = false;
++ if (value > 0)
+ {
+- (*redundancy)
+- ->update("/xyz/openbmc_project/sensors/fan_tach/" + name, !status);
++ status = thresholds::checkThresholds(this);
++
++ if (redundancy && *redundancy)
++ {
++ (*redundancy)
++ ->update("/xyz/openbmc_project/sensors/fan_tach/" + name,
++ !status);
++ }
+ }
+
+ bool curLed = !status;
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors/0005-Fix-PECI-ioctl-number.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors/0005-Fix-PECI-ioctl-number.patch
new file mode 100644
index 000000000..8119f7542
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors/0005-Fix-PECI-ioctl-number.patch
@@ -0,0 +1,29 @@
+From f85dd776301371892ff5197c1995bf2224dd87ab Mon Sep 17 00:00:00 2001
+From: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+Date: Mon, 22 Feb 2021 15:57:20 -0800
+Subject: [PATCH] Fix PECI ioctl number
+
+This commit fixes PECI ioctl number to 0xb8 to avoid conflicts in
+kernel v5.10.
+
+Signed-off-by: Jae Hyun Yoo <jae.hyun.yoo@intel.com>
+---
+ include/linux/peci-ioctl.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/include/linux/peci-ioctl.h b/include/linux/peci-ioctl.h
+index e5b4b8bd3275..1f44edf4fc04 100644
+--- a/include/linux/peci-ioctl.h
++++ b/include/linux/peci-ioctl.h
+@@ -601,7 +601,7 @@ struct peci_crashdump_get_frame_msg {
+ __u8 data[16];
+ } __attribute__((__packed__));
+
+-#define PECI_IOC_BASE 0xb7
++#define PECI_IOC_BASE 0xb8
+
+ #define PECI_IOC_XFER \
+ _IOWR(PECI_IOC_BASE, PECI_CMD_XFER, struct peci_xfer_msg)
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors/0006-CPUSensor-create-RequirediTempSensor-if-defined.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors/0006-CPUSensor-create-RequirediTempSensor-if-defined.patch
new file mode 100644
index 000000000..fb38b0348
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors/0006-CPUSensor-create-RequirediTempSensor-if-defined.patch
@@ -0,0 +1,234 @@
+From f516fc884fcbc03bf560b4ef975ad236232bd1e6 Mon Sep 17 00:00:00 2001
+From: Zhikui Ren <zhikui.ren@intel.com>
+Date: Tue, 11 May 2021 11:14:55 -0700
+Subject: [PATCH] CPUSensor: create RequiredTempSensor if defined
+
+When BMC fails to talk to CPU through PECI, no
+CPU sensors are created. Fan speed control only boost
+fan when input sensor is not available. It does not
+have the knowledge of which sensors are expected to
+be present and can't treat "missing" sensor as failed one.
+The failure on PECI goes unnoticed and we can have a thermal
+run away.
+
+Query sensor config for RequiredTempSensor for any present
+CPUs. Create a CPU sensor that is not available.
+This sensor will be replaced by a normal CPU sensor when
+peci detect the CPU and associated hwmon file is discovered.
+
+This is an initial patch that target to address the particular
+failure case. More work will follow to support a more generic
+"Required" sensor config.
+
+Signed-off-by: Zhikui Ren <zhikui.ren@intel.com>
+---
+ include/CPUSensor.hpp | 9 ++++++
+ src/CPUSensor.cpp | 69 +++++++++++++++++++++++++++++++++++++++++++
+ src/CPUSensorMain.cpp | 54 ++++++++++++++++++++++++++++-----
+ 3 files changed, 124 insertions(+), 8 deletions(-)
+
+diff --git a/include/CPUSensor.hpp b/include/CPUSensor.hpp
+index 29b8209..5d09e4e 100644
+--- a/include/CPUSensor.hpp
++++ b/include/CPUSensor.hpp
+@@ -26,6 +26,15 @@ class CPUSensor : public Sensor
+ std::vector<thresholds::Threshold>&& thresholds,
+ const std::string& configuration, int cpuId, bool show,
+ double dtsOffset);
++
++ // Create a CPUSensor without a path to sensor value
++ CPUSensor(const std::string& objectType,
++ sdbusplus::asio::object_server& objectServer,
++ std::shared_ptr<sdbusplus::asio::connection>& conn,
++ boost::asio::io_service& io, const std::string& sensorName,
++ std::vector<thresholds::Threshold>&& thresholdsIn,
++ const std::string& sensorConfiguration);
++
+ ~CPUSensor() override;
+ static constexpr unsigned int sensorScaleFactor = 1000;
+ static constexpr unsigned int sensorPollMs = 1000;
+diff --git a/src/CPUSensor.cpp b/src/CPUSensor.cpp
+index 7f9a2c5..7c29cf0 100644
+--- a/src/CPUSensor.cpp
++++ b/src/CPUSensor.cpp
+@@ -99,6 +99,75 @@ CPUSensor::CPUSensor(const std::string& path, const std::string& objectType,
+ setupRead();
+ }
+
++// Create a dummy "not available" CPUSensor
++// This is used to indicate a missing required sensor for
++// other services like fan control
++CPUSensor::CPUSensor(const std::string& objectType,
++ sdbusplus::asio::object_server& objectServer,
++ std::shared_ptr<sdbusplus::asio::connection>& conn,
++ boost::asio::io_service& io, const std::string& sensorName,
++ std::vector<thresholds::Threshold>&& thresholdsIn,
++ const std::string& sensorConfiguration) :
++ Sensor(boost::replace_all_copy(sensorName, " ", "_"),
++ std::move(thresholdsIn), sensorConfiguration, objectType, 0, 0, conn,
++ PowerState::on),
++ objServer(objectServer), inputDev(io), waitTimer(io),
++ privTcontrol(std::numeric_limits<double>::quiet_NaN()), dtsOffset(0),
++ show(true), pollTime(CPUSensor::sensorPollMs), minMaxReadCounter(0)
++{
++ // assume it is a temperature sensor for now
++ // support for other type can be added later
++ std::string interfacePath =
++ "/xyz/openbmc_project/sensors/temperature/" + name;
++ const char* units = sensor_paths::unitDegreesC;
++ minValue = -128;
++ maxValue = 127;
++
++ sensorInterface = objectServer.add_interface(
++ interfacePath, "xyz.openbmc_project.Sensor.Value");
++
++ sensorInterface->register_property("Unit", units);
++ sensorInterface->register_property("MaxValue", maxValue);
++ sensorInterface->register_property("MinValue", minValue);
++ sensorInterface->register_property(
++ "Value", value, [&](const double& newValue, double& oldValue) {
++ return setSensorValue(newValue, oldValue);
++ });
++ if (!sensorInterface->initialize())
++ {
++ std::cerr << "error initializing value interface\n";
++ }
++
++ if (!availableInterface)
++ {
++ availableInterface = std::make_shared<sdbusplus::asio::dbus_interface>(
++ conn, sensorInterface->get_object_path(), availableInterfaceName);
++ availableInterface->register_property(
++ "Available", false, [this](const bool propIn, bool& old) {
++ if (propIn == old)
++ {
++ return 1;
++ }
++ old = propIn;
++ if (!propIn)
++ {
++ updateValue(std::numeric_limits<double>::quiet_NaN());
++ }
++ return 1;
++ });
++ availableInterface->initialize();
++ }
++ if (!operationalInterface)
++ {
++ operationalInterface =
++ std::make_shared<sdbusplus::asio::dbus_interface>(
++ conn, sensorInterface->get_object_path(),
++ operationalInterfaceName);
++ operationalInterface->register_property("Functional", true);
++ operationalInterface->initialize();
++ }
++}
++
+ CPUSensor::~CPUSensor()
+ {
+ // close the input dev to cancel async operations
+diff --git a/src/CPUSensorMain.cpp b/src/CPUSensorMain.cpp
+index 92c1716..4c00551 100644
+--- a/src/CPUSensorMain.cpp
++++ b/src/CPUSensorMain.cpp
+@@ -332,10 +332,9 @@ bool createSensors(boost::asio::io_service& io,
+ {
+ if (debug)
+ {
+- std::cout << "Skipped: " << inputPath << ": " << sensorName
+- << " is already created\n";
++ std::cout << "Will be replaced: " << inputPath << ": "
++ << sensorName << " is already created\n";
+ }
+- continue;
+ }
+
+ // check hidden properties
+@@ -636,9 +635,9 @@ void detectCpuAsync(
+ });
+ }
+
+-bool getCpuConfig(const std::shared_ptr<sdbusplus::asio::connection>& systemBus,
++bool getCpuConfig(std::shared_ptr<sdbusplus::asio::connection>& systemBus,
+ boost::container::flat_set<CPUConfig>& cpuConfigs,
+- ManagedObjectType& sensorConfigs,
++ ManagedObjectType& sensorConfigs, boost::asio::io_service& io,
+ sdbusplus::asio::object_server& objectServer)
+ {
+ bool useCache = false;
+@@ -700,6 +699,45 @@ bool getCpuConfig(const std::shared_ptr<sdbusplus::asio::connection>& systemBus,
+ iface->register_property("Present", *present);
+ iface->initialize();
+ inventoryIfaces[name] = std::move(iface);
++ if (*present)
++ {
++ // create required CPU sensors here in unavailable state
++ auto findRequiredTempSensor =
++ config.second.find("RequiredTempSensor");
++ auto findCpuId = config.second.find("CpuID");
++ if (findRequiredTempSensor != config.second.end() &&
++ findCpuId != config.second.end())
++ {
++ std::string label =
++ std::visit(VariantToStringVisitor(),
++ findRequiredTempSensor->second);
++ // for temp sensor hwmon sysfs use input
++ std::string item{"input"};
++ int cpuId =
++ std::visit(VariantToUnsignedIntVisitor(),
++ findCpuId->second);
++ std::string requiredSensorName =
++ createSensorName(label, item, cpuId);
++
++ auto& sensorPtr = gCpuSensors[requiredSensorName];
++ if (sensorPtr == nullptr)
++ {
++ // created a dummy sensor for required sensor,
++ // will be replaced with a real one if it is
++ // detected
++ std::string objectType{};
++ std::vector<thresholds::Threshold>
++ emptyThreshold{};
++ std::string emptyConfig{};
++ sensorPtr = std::make_unique<CPUSensor>(
++ objectType, objectServer, systemBus, io,
++ requiredSensorName,
++ std::move(emptyThreshold), emptyConfig);
++ std::cout << "created required CPU sensor "
++ << requiredSensorName << "\n";
++ }
++ }
++ }
+ }
+
+ auto findBus = config.second.find("Bus");
+@@ -728,7 +766,6 @@ bool getCpuConfig(const std::shared_ptr<sdbusplus::asio::connection>& systemBus,
+ std::cout << "name: " << name << "\n";
+ std::cout << "type: " << type << "\n";
+ }
+-
+ cpuConfigs.emplace(bus, addr, name, State::OFF);
+ }
+ }
+@@ -764,7 +801,8 @@ int main()
+ return; // we're being canceled
+ }
+
+- if (getCpuConfig(systemBus, cpuConfigs, sensorConfigs, objectServer))
++ if (getCpuConfig(systemBus, cpuConfigs, sensorConfigs, io,
++ objectServer))
+ {
+ detectCpuAsync(pingTimer, creationTimer, io, objectServer,
+ systemBus, cpuConfigs, sensorConfigs);
+@@ -792,7 +830,7 @@ int main()
+ return; // we're being canceled
+ }
+
+- if (getCpuConfig(systemBus, cpuConfigs, sensorConfigs,
++ if (getCpuConfig(systemBus, cpuConfigs, sensorConfigs, io,
+ objectServer))
+ {
+ detectCpuAsync(pingTimer, creationTimer, io, objectServer,
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors/intrusionsensor-depend-on-networkd.conf b/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors/intrusionsensor-depend-on-networkd.conf
new file mode 100644
index 000000000..6f0fd3ffc
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors/intrusionsensor-depend-on-networkd.conf
@@ -0,0 +1,3 @@
+[Unit]
+After=systemd-networkd.service
+Requires=systemd-networkd.service
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors_%.bbappend
new file mode 100644
index 000000000..361e425e5
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors_%.bbappend
@@ -0,0 +1,43 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+PROJECT_SRC_DIR := "${THISDIR}/${PN}"
+
+SRCREV = "13b63f8f597d396db8b5bd182ac2e5814d599e2f"
+#SRC_URI = "git://github.com/openbmc/dbus-sensors.git"
+
+SRC_URI += "\
+ file://intrusionsensor-depend-on-networkd.conf \
+ file://0001-Add-check-for-min-max-received-from-hwmon-files.patch \
+ file://0002-Fix-PECI-client-creation-flow.patch \
+ file://0003-Fix-missing-threshold-de-assert-event-when-threshold.patch \
+ file://0004-Fan-Tach-Sensor-Threshold-Ignore-Zero.patch \
+ file://0005-Fix-PECI-ioctl-number.patch \
+ file://0006-CPUSensor-create-RequirediTempSensor-if-defined.patch \
+ "
+
+DEPENDS_append = " libgpiod libmctp"
+
+PACKAGECONFIG += " \
+ adcsensor \
+ cpusensor \
+ exitairtempsensor \
+ fansensor \
+ hwmontempsensor \
+ intrusionsensor \
+ ipmbsensor \
+ mcutempsensor \
+ psusensor \
+"
+
+PACKAGECONFIG[nvmesensor] = "-Dnvme=enabled, -Dnvme=disabled"
+
+SYSTEMD_SERVICE_${PN} += "${@bb.utils.contains('PACKAGECONFIG', 'nvmesensor', \
+ 'xyz.openbmc_project.nvmesensor.service', \
+ '', d)}"
+
+do_install_append() {
+ svc="xyz.openbmc_project.intrusionsensor.service"
+ srcf="${WORKDIR}/intrusionsensor-depend-on-networkd.conf"
+ dstf="${D}/etc/systemd/system/${svc}.d/10-depend-on-networkd.conf"
+ mkdir -p "${D}/etc/systemd/system/${svc}.d"
+ install "${srcf}" "${dstf}"
+}