blob: 165cf2b67269faea76e7d8d46a8af76bbd838be0 [file] [log] [blame]
Nikhil Potadeb669b6b2019-03-13 10:52:21 -07001/*
2// Copyright (c) 2019 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16
Andrew Jefferye3e3c972021-05-26 14:37:07 +093017#include <NVMeBasicContext.hpp>
Andrew Jefferydae6e182021-05-21 16:23:07 +093018#include <NVMeContext.hpp>
Andrew Jefferya9d15082021-05-24 13:55:12 +093019#include <NVMeMCTPContext.hpp>
Ed Tanous8a57ec02020-10-09 12:46:52 -070020#include <NVMeSensor.hpp>
Nikhil Potadeb669b6b2019-03-13 10:52:21 -070021#include <boost/asio/deadline_timer.hpp>
James Feist38fb5982020-05-28 10:09:54 -070022
Andrew Jeffery34123562021-12-02 14:38:41 +103023#include <optional>
Nikhil Potadeb669b6b2019-03-13 10:52:21 -070024#include <regex>
25
Nikhil Potadeb669b6b2019-03-13 10:52:21 -070026static NVMEMap nvmeDeviceMap;
27
Ed Tanous8a57ec02020-10-09 12:46:52 -070028static constexpr bool debug = false;
Nikhil Potadeb669b6b2019-03-13 10:52:21 -070029
30NVMEMap& getNVMEMap()
31{
32 return nvmeDeviceMap;
33}
34
Andrew Jeffery34123562021-12-02 14:38:41 +103035static std::optional<int>
36 extractBusNumber(const std::string& path,
37 const SensorBaseConfigMap& properties)
38{
39 auto findBus = properties.find("Bus");
40 if (findBus == properties.end())
41 {
42 std::cerr << "could not determine bus number for " << path << "\n";
43 return std::nullopt;
44 }
45
46 return std::visit(VariantToIntVisitor(), findBus->second);
47}
48
Andrew Jefferye671f052021-12-02 14:47:20 +103049static std::optional<std::string>
50 extractSensorName(const std::string& path,
51 const SensorBaseConfigMap& properties)
52{
53 auto findSensorName = properties.find("Name");
54 if (findSensorName == properties.end())
55 {
56 std::cerr << "could not determine configuration name for " << path
57 << "\n";
58 return std::nullopt;
59 }
60
61 return std::get<std::string>(findSensorName->second);
62}
63
Andrew Jeffery710562a2021-12-02 14:55:55 +103064static std::filesystem::path deriveRootBusPath(int busNumber)
65{
66 return "/sys/bus/i2c/devices/i2c-" + std::to_string(busNumber) +
67 "/mux_device";
68}
69
Andrew Jeffery66ab8402021-12-02 15:03:51 +103070static std::optional<int> deriveRootBus(std::optional<int> busNumber)
71{
72 if (!busNumber)
73 {
74 return std::nullopt;
75 }
76
77 std::filesystem::path muxPath = deriveRootBusPath(*busNumber);
78
79 if (!std::filesystem::is_symlink(muxPath))
80 {
81 return *busNumber;
82 }
83
84 std::string rootName = std::filesystem::read_symlink(muxPath).filename();
85 size_t dash = rootName.find('-');
86 if (dash == std::string::npos)
87 {
88 std::cerr << "Error finding root bus for " << rootName << "\n";
89 return std::nullopt;
90 }
91
92 return std::stoi(rootName.substr(0, dash));
93}
94
Andrew Jefferyc7a89e52021-12-02 15:10:23 +103095static std::shared_ptr<NVMeContext>
96 provideRootBusContext(boost::asio::io_service& io, NVMEMap& map,
97 int rootBus)
98{
99 auto findRoot = map.find(rootBus);
100 if (findRoot != map.end())
101 {
102 return findRoot->second;
103 }
104
105 std::shared_ptr<NVMeContext> context =
106#if HAVE_NVME_MI_MCTP
107 std::make_shared<NVMeMCTPContext>(io, rootBus);
108#else
109 std::make_shared<NVMeBasicContext>(io, rootBus);
110#endif
111 map[rootBus] = context;
112
113 return context;
114}
115
Andrew Jefferyf690f0c2021-12-02 11:42:58 +1030116static void handleSensorConfigurations(
117 boost::asio::io_service& io, sdbusplus::asio::object_server& objectServer,
118 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
119 const ManagedObjectType& sensorConfigurations)
120{
121 // todo: it'd be better to only update the ones we care about
122 for (const auto& [_, nvmeContextPtr] : nvmeDeviceMap)
123 {
124 if (nvmeContextPtr)
125 {
126 nvmeContextPtr->close();
127 }
128 }
129 nvmeDeviceMap.clear();
130
131 // iterate through all found configurations
Andrew Jefferyee164342021-12-02 16:02:19 +1030132 for (const auto& [interfacePath, sensorData] : sensorConfigurations)
Andrew Jefferyf690f0c2021-12-02 11:42:58 +1030133 {
Andrew Jefferyf690f0c2021-12-02 11:42:58 +1030134 // find base configuration
Andrew Jeffery0c23fc32021-12-08 16:48:30 +1030135 auto sensorBase = sensorData.find(NVMeSensor::CONFIG_TYPE);
Andrew Jefferyee164342021-12-02 16:02:19 +1030136 if (sensorBase != sensorData.end())
Andrew Jefferyf690f0c2021-12-02 11:42:58 +1030137 {
Andrew Jefferyee164342021-12-02 16:02:19 +1030138 const SensorBaseConfigMap& sensorConfig = sensorBase->second;
139 std::optional<int> busNumber =
140 extractBusNumber(interfacePath, sensorConfig);
141 std::optional<std::string> sensorName =
142 extractSensorName(interfacePath, sensorConfig);
143 std::optional<int> rootBus = deriveRootBus(busNumber);
144
145 if (!(busNumber && sensorName && rootBus))
146 {
147 continue;
148 }
149
150 std::vector<thresholds::Threshold> sensorThresholds;
151 if (!parseThresholdsFromConfig(sensorData, sensorThresholds))
152 {
153 std::cerr << "error populating thresholds for " << *sensorName
154 << "\n";
155 }
156
157 std::shared_ptr<NVMeSensor> sensorPtr =
158 std::make_shared<NVMeSensor>(
159 objectServer, io, dbusConnection, *sensorName,
160 std::move(sensorThresholds), interfacePath, *busNumber);
161
Andrew Jeffery57574ad2021-12-02 16:35:52 +1030162 provideRootBusContext(io, nvmeDeviceMap, *rootBus)
163 ->addSensor(sensorPtr);
Andrew Jefferyf690f0c2021-12-02 11:42:58 +1030164 }
Andrew Jefferyf690f0c2021-12-02 11:42:58 +1030165 }
166 for (const auto& [_, context] : nvmeDeviceMap)
167 {
168 context->pollNVMeDevices();
169 }
170}
171
Nikhil Potadeb669b6b2019-03-13 10:52:21 -0700172void createSensors(boost::asio::io_service& io,
173 sdbusplus::asio::object_server& objectServer,
174 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection)
175{
176
177 auto getter = std::make_shared<GetSensorConfiguration>(
178 dbusConnection,
179 std::move([&io, &objectServer, &dbusConnection](
180 const ManagedObjectType& sensorConfigurations) {
Andrew Jefferyf690f0c2021-12-02 11:42:58 +1030181 handleSensorConfigurations(io, objectServer, dbusConnection,
182 sensorConfigurations);
Nikhil Potadeb669b6b2019-03-13 10:52:21 -0700183 }));
Andrew Jeffery0c23fc32021-12-08 16:48:30 +1030184 getter->getConfiguration(std::vector<std::string>{NVMeSensor::CONFIG_TYPE});
Nikhil Potadeb669b6b2019-03-13 10:52:21 -0700185}
186
187int main()
188{
189 boost::asio::io_service io;
190 auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
191 systemBus->request_name("xyz.openbmc_project.NVMeSensor");
192 sdbusplus::asio::object_server objectServer(systemBus);
Andrew Jeffery6f25e7e2021-05-24 12:52:53 +0930193#if HAVE_NVME_MI_MCTP
Nikhil Potadeb669b6b2019-03-13 10:52:21 -0700194 nvmeMCTP::init();
Andrew Jeffery6f25e7e2021-05-24 12:52:53 +0930195#endif
Nikhil Potadeb669b6b2019-03-13 10:52:21 -0700196
197 io.post([&]() { createSensors(io, objectServer, systemBus); });
198
199 boost::asio::deadline_timer filterTimer(io);
200 std::function<void(sdbusplus::message::message&)> eventHandler =
201 [&filterTimer, &io, &objectServer,
James Feist7d7579f2020-09-02 14:13:08 -0700202 &systemBus](sdbusplus::message::message&) {
Nikhil Potadeb669b6b2019-03-13 10:52:21 -0700203 // this implicitly cancels the timer
204 filterTimer.expires_from_now(boost::posix_time::seconds(1));
205
206 filterTimer.async_wait([&](const boost::system::error_code& ec) {
207 if (ec == boost::asio::error::operation_aborted)
208 {
209 return; // we're being canceled
210 }
Andrew Jeffery7279f932021-05-25 13:35:27 +0930211
212 if (ec)
Nikhil Potadeb669b6b2019-03-13 10:52:21 -0700213 {
214 std::cerr << "Error: " << ec.message() << "\n";
215 return;
216 }
217
218 createSensors(io, objectServer, systemBus);
219 });
220 };
221
222 sdbusplus::bus::match::match configMatch(
223 static_cast<sdbusplus::bus::bus&>(*systemBus),
224 "type='signal',member='PropertiesChanged',path_namespace='" +
225 std::string(inventoryPath) + "',arg0namespace='" +
Andrew Jeffery0c23fc32021-12-08 16:48:30 +1030226 std::string(NVMeSensor::CONFIG_TYPE) + "'",
Nikhil Potadeb669b6b2019-03-13 10:52:21 -0700227 eventHandler);
228
Bruce Lee1263c3d2021-06-04 15:16:33 +0800229 setupManufacturingModeMatch(*systemBus);
Nikhil Potadeb669b6b2019-03-13 10:52:21 -0700230 io.run();
231}