blob: fc9eb2ff4e49b94b2edfe7fd2fa342079ad90252 [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 Jefferydae6e182021-05-21 16:23:07 +093017#include <NVMeContext.hpp>
Andrew Jefferya9d15082021-05-24 13:55:12 +093018#include <NVMeMCTPContext.hpp>
Ed Tanous8a57ec02020-10-09 12:46:52 -070019#include <NVMeSensor.hpp>
Nikhil Potadeb669b6b2019-03-13 10:52:21 -070020#include <boost/asio/deadline_timer.hpp>
James Feist38fb5982020-05-28 10:09:54 -070021
Nikhil Potadeb669b6b2019-03-13 10:52:21 -070022#include <regex>
23
24static constexpr const char* sensorType =
25 "xyz.openbmc_project.Configuration.NVME1000";
26
27static NVMEMap nvmeDeviceMap;
28
Ed Tanous8a57ec02020-10-09 12:46:52 -070029static constexpr bool debug = false;
Nikhil Potadeb669b6b2019-03-13 10:52:21 -070030
31NVMEMap& getNVMEMap()
32{
33 return nvmeDeviceMap;
34}
35
36void createSensors(boost::asio::io_service& io,
37 sdbusplus::asio::object_server& objectServer,
38 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection)
39{
40
41 auto getter = std::make_shared<GetSensorConfiguration>(
42 dbusConnection,
43 std::move([&io, &objectServer, &dbusConnection](
44 const ManagedObjectType& sensorConfigurations) {
45 // todo: it'd be better to only update the ones we care about
James Feist375ade22020-07-16 16:32:10 -070046 for (const auto& [_, nvmeContextPtr] : nvmeDeviceMap)
47 {
48 if (nvmeContextPtr)
49 {
50 nvmeContextPtr->close();
51 }
52 }
Nikhil Potadeb669b6b2019-03-13 10:52:21 -070053 nvmeDeviceMap.clear();
54
55 // iterate through all found configurations
56 for (const std::pair<sdbusplus::message::object_path, SensorData>&
57 sensor : sensorConfigurations)
58 {
59 const SensorData& sensorData = sensor.second;
60 const std::string& interfacePath = sensor.first.str;
61 const std::pair<
62 std::string,
63 boost::container::flat_map<std::string, BasicVariantType>>*
64 baseConfiguration = nullptr;
65
66 // find base configuration
67 auto sensorBase = sensor.second.find(sensorType);
68 if (sensorBase != sensor.second.end())
69 {
70 baseConfiguration = &(*sensorBase);
71 }
72
73 if (baseConfiguration == nullptr)
74 {
75 continue;
76 }
77 auto findBus = baseConfiguration->second.find("Bus");
78 if (findBus == baseConfiguration->second.end())
79 {
80 continue;
81 }
82
Andrew Jeffery9f315582021-05-25 13:32:14 +093083 int busNumber =
84 std::visit(VariantToIntVisitor(), findBus->second);
Nikhil Potadeb669b6b2019-03-13 10:52:21 -070085
86 auto findSensorName = baseConfiguration->second.find("Name");
87 if (findSensorName == baseConfiguration->second.end())
88 {
89 std::cerr << "could not determine configuration name for "
90 << interfacePath << "\n";
91 continue;
92 }
93 std::string sensorName =
94 std::get<std::string>(findSensorName->second);
95
96 std::vector<thresholds::Threshold> sensorThresholds;
97
98 if (!parseThresholdsFromConfig(sensorData, sensorThresholds))
99 {
100 std::cerr << "error populating thresholds for "
101 << sensorName << "\n";
102 }
103
104 int rootBus = busNumber;
105
106 std::string muxPath = "/sys/bus/i2c/devices/i2c-" +
107 std::to_string(busNumber) + "/mux_device";
108
109 if (std::filesystem::is_symlink(muxPath))
110 {
111 std::string rootName =
112 std::filesystem::read_symlink(muxPath).filename();
Andrew Jefferyc12ceac2021-05-25 13:34:06 +0930113 size_t dash = rootName.find('-');
Nikhil Potadeb669b6b2019-03-13 10:52:21 -0700114 if (dash == std::string::npos)
115 {
116 std::cerr << "Error finding root bus for " << rootName
117 << "\n";
118 continue;
119 }
120 rootBus = std::stoi(rootName.substr(0, dash));
121 }
122
123 std::shared_ptr<NVMeContext> context;
124 auto findRoot = nvmeDeviceMap.find(rootBus);
125 if (findRoot != nvmeDeviceMap.end())
126 {
127 context = findRoot->second;
128 }
129 else
130 {
Andrew Jefferya9d15082021-05-24 13:55:12 +0930131 context = std::make_shared<NVMeMCTPContext>(io, rootBus);
Nikhil Potadeb669b6b2019-03-13 10:52:21 -0700132 nvmeDeviceMap[rootBus] = context;
133 }
134
135 std::shared_ptr<NVMeSensor> sensorPtr =
136 std::make_shared<NVMeSensor>(
137 objectServer, io, dbusConnection, sensorName,
138 std::move(sensorThresholds), interfacePath, busNumber);
139
Andrew Jefferyfa500ae2021-05-21 16:46:36 +0930140 context->addSensor(sensorPtr);
Nikhil Potadeb669b6b2019-03-13 10:52:21 -0700141 }
142 for (const auto& [_, context] : nvmeDeviceMap)
143 {
144 context->pollNVMeDevices();
145 }
146 }));
147 getter->getConfiguration(std::vector<std::string>{sensorType});
148}
149
150int main()
151{
152 boost::asio::io_service io;
153 auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
154 systemBus->request_name("xyz.openbmc_project.NVMeSensor");
155 sdbusplus::asio::object_server objectServer(systemBus);
156 nvmeMCTP::init();
157
158 io.post([&]() { createSensors(io, objectServer, systemBus); });
159
160 boost::asio::deadline_timer filterTimer(io);
161 std::function<void(sdbusplus::message::message&)> eventHandler =
162 [&filterTimer, &io, &objectServer,
James Feist7d7579f2020-09-02 14:13:08 -0700163 &systemBus](sdbusplus::message::message&) {
Nikhil Potadeb669b6b2019-03-13 10:52:21 -0700164 // this implicitly cancels the timer
165 filterTimer.expires_from_now(boost::posix_time::seconds(1));
166
167 filterTimer.async_wait([&](const boost::system::error_code& ec) {
168 if (ec == boost::asio::error::operation_aborted)
169 {
170 return; // we're being canceled
171 }
Andrew Jeffery7279f932021-05-25 13:35:27 +0930172
173 if (ec)
Nikhil Potadeb669b6b2019-03-13 10:52:21 -0700174 {
175 std::cerr << "Error: " << ec.message() << "\n";
176 return;
177 }
178
179 createSensors(io, objectServer, systemBus);
180 });
181 };
182
183 sdbusplus::bus::match::match configMatch(
184 static_cast<sdbusplus::bus::bus&>(*systemBus),
185 "type='signal',member='PropertiesChanged',path_namespace='" +
186 std::string(inventoryPath) + "',arg0namespace='" +
187 std::string(sensorType) + "'",
188 eventHandler);
189
Bruce Lee1263c3d2021-06-04 15:16:33 +0800190 setupManufacturingModeMatch(*systemBus);
Nikhil Potadeb669b6b2019-03-13 10:52:21 -0700191 io.run();
192}