Enabling NVMe sensor support
This commit introduces the support for NVMe drives for sensors.
All the NVMe drives which are detected by the FRU manager and are
present in the inventory are scanned at regular interval for reading
the temperature values of the NVMe devices.
Tested:
NAME TYPE SIGNATURE RESULT/VALUE
org.freedesktop.DBus.Introspectable interface - -
.Introspect method - s
org.freedesktop.DBus.Peer interface - -
.GetMachineId method - s
.Ping method - -
org.freedesktop.DBus.Properties interface - -
.Get method ss v
.GetAll method s a{sv}
.Set method ssv -
.PropertiesChanged signal sa{sv}as -
xyz.openbmc_project.Association.Definitions interface - -
.Associations property a(sss) 1 "chassis" "all_sensors" "/xyz/openb...
xyz.openbmc_project.Sensor.Threshold.Critical interface - -
.CriticalAlarmHigh property b false
.CriticalAlarmLow property b false
.CriticalHigh property d 115
.CriticalLow property d 0
xyz.openbmc_project.Sensor.Threshold.Warning interface - -
.WarningAlarmHigh property b false
.WarningAlarmLow property b false
.WarningHigh property d 110
.WarningLow property d 5
xyz.openbmc_project.Sensor.Value interface - -
.MaxValue property d 127
.MinValue property d -60
.Value property d 22
Change-Id: Icb119b424234d548c8ff5cda9c7a9517ec9696bb
Signed-off-by: Nikhil Potade <nikhil.potade@linux.intel.com>
Signed-off-by: James Feist <james.feist@linux.intel.com>
diff --git a/src/NVMeSensorMain.cpp b/src/NVMeSensorMain.cpp
new file mode 100644
index 0000000..1858ea9
--- /dev/null
+++ b/src/NVMeSensorMain.cpp
@@ -0,0 +1,181 @@
+/*
+// Copyright (c) 2019 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include "NVMeSensor.hpp"
+
+#include <boost/asio/deadline_timer.hpp>
+#include <regex>
+
+static constexpr const char* sensorType =
+ "xyz.openbmc_project.Configuration.NVME1000";
+
+static NVMEMap nvmeDeviceMap;
+
+static constexpr bool DEBUG = false;
+
+NVMEMap& getNVMEMap()
+{
+ return nvmeDeviceMap;
+}
+
+void createSensors(boost::asio::io_service& io,
+ sdbusplus::asio::object_server& objectServer,
+ std::shared_ptr<sdbusplus::asio::connection>& dbusConnection)
+{
+
+ auto getter = std::make_shared<GetSensorConfiguration>(
+ dbusConnection,
+ std::move([&io, &objectServer, &dbusConnection](
+ const ManagedObjectType& sensorConfigurations) {
+ // todo: it'd be better to only update the ones we care about
+ nvmeDeviceMap.clear();
+
+ // iterate through all found configurations
+ for (const std::pair<sdbusplus::message::object_path, SensorData>&
+ sensor : sensorConfigurations)
+ {
+ const SensorData& sensorData = sensor.second;
+ const std::string& interfacePath = sensor.first.str;
+ const std::pair<
+ std::string,
+ boost::container::flat_map<std::string, BasicVariantType>>*
+ baseConfiguration = nullptr;
+
+ // find base configuration
+ auto sensorBase = sensor.second.find(sensorType);
+ if (sensorBase != sensor.second.end())
+ {
+ baseConfiguration = &(*sensorBase);
+ }
+
+ if (baseConfiguration == nullptr)
+ {
+ continue;
+ }
+ auto findBus = baseConfiguration->second.find("Bus");
+ if (findBus == baseConfiguration->second.end())
+ {
+ continue;
+ }
+
+ unsigned int busNumber =
+ std::visit(VariantToUnsignedIntVisitor(), findBus->second);
+
+ auto findSensorName = baseConfiguration->second.find("Name");
+ if (findSensorName == baseConfiguration->second.end())
+ {
+ std::cerr << "could not determine configuration name for "
+ << interfacePath << "\n";
+ continue;
+ }
+ std::string sensorName =
+ std::get<std::string>(findSensorName->second);
+
+ std::vector<thresholds::Threshold> sensorThresholds;
+
+ if (!parseThresholdsFromConfig(sensorData, sensorThresholds))
+ {
+ std::cerr << "error populating thresholds for "
+ << sensorName << "\n";
+ }
+
+ int rootBus = busNumber;
+
+ std::string muxPath = "/sys/bus/i2c/devices/i2c-" +
+ std::to_string(busNumber) + "/mux_device";
+
+ if (std::filesystem::is_symlink(muxPath))
+ {
+ std::string rootName =
+ std::filesystem::read_symlink(muxPath).filename();
+ size_t dash = rootName.find("-");
+ if (dash == std::string::npos)
+ {
+ std::cerr << "Error finding root bus for " << rootName
+ << "\n";
+ continue;
+ }
+ rootBus = std::stoi(rootName.substr(0, dash));
+ }
+
+ std::shared_ptr<NVMeContext> context;
+ auto findRoot = nvmeDeviceMap.find(rootBus);
+ if (findRoot != nvmeDeviceMap.end())
+ {
+ context = findRoot->second;
+ }
+ else
+ {
+ context = std::make_shared<NVMeContext>(io, rootBus);
+ nvmeDeviceMap[rootBus] = context;
+ }
+
+ std::shared_ptr<NVMeSensor> sensorPtr =
+ std::make_shared<NVMeSensor>(
+ objectServer, io, dbusConnection, sensorName,
+ std::move(sensorThresholds), interfacePath, busNumber);
+
+ context->sensors.emplace_back(sensorPtr);
+ }
+ for (const auto& [_, context] : nvmeDeviceMap)
+ {
+ context->pollNVMeDevices();
+ }
+ }));
+ getter->getConfiguration(std::vector<std::string>{sensorType});
+}
+
+int main()
+{
+ boost::asio::io_service io;
+ auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
+ systemBus->request_name("xyz.openbmc_project.NVMeSensor");
+ sdbusplus::asio::object_server objectServer(systemBus);
+ nvmeMCTP::init();
+
+ io.post([&]() { createSensors(io, objectServer, systemBus); });
+
+ boost::asio::deadline_timer filterTimer(io);
+ std::function<void(sdbusplus::message::message&)> eventHandler =
+ [&filterTimer, &io, &objectServer,
+ &systemBus](sdbusplus::message::message& message) {
+ // this implicitly cancels the timer
+ filterTimer.expires_from_now(boost::posix_time::seconds(1));
+
+ filterTimer.async_wait([&](const boost::system::error_code& ec) {
+ if (ec == boost::asio::error::operation_aborted)
+ {
+ return; // we're being canceled
+ }
+ else if (ec)
+ {
+ std::cerr << "Error: " << ec.message() << "\n";
+ return;
+ }
+
+ createSensors(io, objectServer, systemBus);
+ });
+ };
+
+ sdbusplus::bus::match::match configMatch(
+ static_cast<sdbusplus::bus::bus&>(*systemBus),
+ "type='signal',member='PropertiesChanged',path_namespace='" +
+ std::string(inventoryPath) + "',arg0namespace='" +
+ std::string(sensorType) + "'",
+ eventHandler);
+
+ io.run();
+}