blob: 3af20a040ccda98743c0d9ebe0945a82e88d9cfe [file] [log] [blame]
James Feist6714a252018-09-10 15:26:18 -07001/*
2// Copyright (c) 2018 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
James Feistcf3bce62019-01-08 10:07:19 -080017#include "filesystem.hpp"
18
James Feist6714a252018-09-10 15:26:18 -070019#include <fcntl.h>
James Feist6714a252018-09-10 15:26:18 -070020
21#include <CPUSensor.hpp>
22#include <Utils.hpp>
23#include <VariantVisitors.hpp>
24#include <boost/algorithm/string/predicate.hpp>
25#include <boost/algorithm/string/replace.hpp>
26#include <boost/container/flat_set.hpp>
27#include <boost/date_time/posix_time/posix_time.hpp>
28#include <boost/process/child.hpp>
James Feist6714a252018-09-10 15:26:18 -070029#include <fstream>
30#include <regex>
31#include <sdbusplus/asio/connection.hpp>
32#include <sdbusplus/asio/object_server.hpp>
33
James Feistf87dc4c2018-12-05 14:39:51 -080034// clang-format off
35// this needs to be included last or we'll have build issues
36#include <linux/peci-ioctl.h>
37// clang-format on
38
James Feist6714a252018-09-10 15:26:18 -070039static constexpr bool DEBUG = false;
40
41enum State
42{
43 OFF, // host powered down
44 ON, // host powered on
45 READY // host powered on and mem test passed - fully ready
46};
47
48struct CPUConfig
49{
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -070050 CPUConfig(const uint64_t& bus, const uint64_t& addr,
51 const std::string& name, const State& state) :
52 bus(bus),
53 addr(addr), name(name), state(state)
James Feist6714a252018-09-10 15:26:18 -070054 {
55 }
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -070056 int bus;
James Feist6714a252018-09-10 15:26:18 -070057 int addr;
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -070058 std::string name;
James Feist6714a252018-09-10 15:26:18 -070059 State state;
60
61 bool operator<(const CPUConfig& rhs) const
62 {
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -070063 return (name < rhs.name);
James Feist6714a252018-09-10 15:26:18 -070064 }
65};
66
Jae Hyun Yoo9c55e6a2018-10-26 10:09:01 -070067static constexpr const char* peciDev = "/dev/peci-";
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -070068static constexpr const unsigned int rankNumMax = 8;
James Feist6714a252018-09-10 15:26:18 -070069
James Feistcf3bce62019-01-08 10:07:19 -080070namespace fs = std::filesystem;
James Feist3eb82622019-02-08 13:10:22 -080071
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -070072static constexpr const char* configPrefix =
James Feist6714a252018-09-10 15:26:18 -070073 "xyz.openbmc_project.Configuration.";
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -070074static constexpr std::array<const char*, 3> sensorTypes = {
James Feist6714a252018-09-10 15:26:18 -070075 "SkylakeCPU", "BroadwellCPU", "HaswellCPU"};
76
Jae Hyun Yood64262b2018-11-01 13:31:16 -070077void detectCpuAsync(
78 boost::asio::deadline_timer& pingTimer,
79 boost::asio::deadline_timer& creationTimer, boost::asio::io_service& io,
80 sdbusplus::asio::object_server& objectServer,
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -080081 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
Jae Hyun Yood64262b2018-11-01 13:31:16 -070082 boost::container::flat_map<std::string, std::unique_ptr<CPUSensor>>&
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -080083 cpuSensors,
84 boost::container::flat_set<CPUConfig>& cpuConfigs,
85 ManagedObjectType& sensorConfigs);
Jae Hyun Yood64262b2018-11-01 13:31:16 -070086
Yoo, Jae Hyunf78d0a42018-10-10 11:03:11 -070087bool createSensors(
James Feist6714a252018-09-10 15:26:18 -070088 boost::asio::io_service& io, sdbusplus::asio::object_server& objectServer,
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -080089 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
James Feist6714a252018-09-10 15:26:18 -070090 boost::container::flat_map<std::string, std::unique_ptr<CPUSensor>>&
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -080091 cpuSensors,
92 boost::container::flat_set<CPUConfig>& cpuConfigs,
93 ManagedObjectType& sensorConfigs)
James Feist6714a252018-09-10 15:26:18 -070094{
95 bool available = false;
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -080096 for (const CPUConfig& cpu : cpuConfigs)
James Feist6714a252018-09-10 15:26:18 -070097 {
98 if (cpu.state != State::OFF)
99 {
100 available = true;
101 break;
102 }
103 }
104 if (!available)
105 {
Yoo, Jae Hyunf78d0a42018-10-10 11:03:11 -0700106 return false;
James Feist6714a252018-09-10 15:26:18 -0700107 }
108
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -0800109 if (sensorConfigs.empty())
James Feist6714a252018-09-10 15:26:18 -0700110 {
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -0800111 return false;
James Feist6714a252018-09-10 15:26:18 -0700112 }
113
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700114 std::vector<fs::path> hwmonNamePaths;
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700115 if (!findFiles(fs::path(R"(/sys/bus/peci/devices)"),
116 R"(peci-\d+/\d+-.+/peci-.+/hwmon/hwmon\d+/name$)",
117 hwmonNamePaths, 1))
James Feist6714a252018-09-10 15:26:18 -0700118 {
119 std::cerr << "No CPU sensors in system\n";
Yoo, Jae Hyunf78d0a42018-10-10 11:03:11 -0700120 return true;
James Feist6714a252018-09-10 15:26:18 -0700121 }
122
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700123 boost::container::flat_set<std::string> scannedDirectories;
124 boost::container::flat_set<std::string> createdSensors;
125
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -0800126 for (const fs::path& hwmonNamePath : hwmonNamePaths)
James Feist6714a252018-09-10 15:26:18 -0700127 {
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700128 const std::string& pathStr = hwmonNamePath.string();
129 auto hwmonDirectory = hwmonNamePath.parent_path();
130
131 auto ret = scannedDirectories.insert(hwmonDirectory.string());
132 if (!ret.second)
James Feist6714a252018-09-10 15:26:18 -0700133 {
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700134 continue; // already searched this path
135 }
136
137 fs::path::iterator it = hwmonNamePath.begin();
138 std::advance(it, 6); // pick the 6th part for a PECI client device name
139 std::string deviceName = *it;
140 auto findHyphen = deviceName.find("-");
141 if (findHyphen == std::string::npos)
142 {
143 std::cerr << "found bad device " << deviceName << "\n";
James Feist6714a252018-09-10 15:26:18 -0700144 continue;
145 }
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700146 std::string busStr = deviceName.substr(0, findHyphen);
147 std::string addrStr = deviceName.substr(findHyphen + 1);
148
149 size_t bus = 0;
150 size_t addr = 0;
151 try
152 {
153 bus = std::stoi(busStr);
154 addr = std::stoi(addrStr, 0, 16);
155 }
156 catch (std::invalid_argument)
157 {
158 continue;
159 }
160
161 std::ifstream nameFile(hwmonNamePath);
162 if (!nameFile.good())
163 {
164 std::cerr << "Failure reading " << hwmonNamePath << "\n";
165 continue;
166 }
167 std::string hwmonName;
168 std::getline(nameFile, hwmonName);
James Feist6714a252018-09-10 15:26:18 -0700169 nameFile.close();
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -0800170 if (hwmonName.empty())
James Feist6714a252018-09-10 15:26:18 -0700171 {
172 // shouldn't have an empty name file
173 continue;
174 }
James Feist6714a252018-09-10 15:26:18 -0700175 if (DEBUG)
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700176 {
177 std::cout << "Checking: " << hwmonNamePath << ": " << hwmonName
178 << "\n";
179 }
James Feist6714a252018-09-10 15:26:18 -0700180
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700181 std::string sensorType;
James Feist6714a252018-09-10 15:26:18 -0700182 const SensorData* sensorData = nullptr;
183 const std::string* interfacePath = nullptr;
James Feist6714a252018-09-10 15:26:18 -0700184 const std::pair<std::string, boost::container::flat_map<
185 std::string, BasicVariantType>>*
186 baseConfiguration = nullptr;
James Feist6714a252018-09-10 15:26:18 -0700187
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700188 for (const std::pair<sdbusplus::message::object_path, SensorData>&
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -0800189 sensor : sensorConfigs)
James Feist6714a252018-09-10 15:26:18 -0700190 {
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700191 sensorData = &(sensor.second);
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700192 for (const char* type : sensorTypes)
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700193 {
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700194 sensorType = configPrefix + std::string(type);
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700195 auto sensorBase = sensorData->find(sensorType);
196 if (sensorBase != sensorData->end())
197 {
198 baseConfiguration = &(*sensorBase);
199 break;
200 }
201 }
202 if (baseConfiguration == nullptr)
203 {
204 std::cerr << "error finding base configuration for" << hwmonName
205 << "\n";
206 continue;
207 }
208 auto configurationBus = baseConfiguration->second.find("Bus");
209 auto configurationAddress =
210 baseConfiguration->second.find("Address");
211
212 if (configurationBus == baseConfiguration->second.end() ||
213 configurationAddress == baseConfiguration->second.end())
214 {
215 std::cerr << "error finding bus or address in configuration";
216 continue;
217 }
218
James Feist3eb82622019-02-08 13:10:22 -0800219 if (std::get<uint64_t>(configurationBus->second) != bus ||
220 std::get<uint64_t>(configurationAddress->second) != addr)
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700221 {
222 continue;
223 }
224
225 interfacePath = &(sensor.first.str);
226 break;
227 }
228 if (interfacePath == nullptr)
229 {
230 std::cerr << "failed to find match for " << hwmonName << "\n";
James Feist6714a252018-09-10 15:26:18 -0700231 continue;
232 }
233
234 auto findCpuId = baseConfiguration->second.find("CpuID");
235 if (findCpuId == baseConfiguration->second.end())
236 {
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700237 std::cerr << "could not determine CPU ID for " << hwmonName << "\n";
James Feist6714a252018-09-10 15:26:18 -0700238 continue;
239 }
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700240 int cpuId =
James Feist3eb82622019-02-08 13:10:22 -0800241 std::visit(VariantToUnsignedIntVisitor(), findCpuId->second);
James Feist6714a252018-09-10 15:26:18 -0700242
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700243 auto directory = hwmonNamePath.parent_path();
James Feist6714a252018-09-10 15:26:18 -0700244 std::vector<fs::path> inputPaths;
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700245 if (!findFiles(fs::path(directory), R"(temp\d+_input$)", inputPaths, 0))
James Feist6714a252018-09-10 15:26:18 -0700246 {
247 std::cerr << "No temperature sensors in system\n";
248 continue;
249 }
250
251 // iterate through all found temp sensors
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -0800252 for (const auto& inputPath : inputPaths)
James Feist6714a252018-09-10 15:26:18 -0700253 {
254 auto inputPathStr = inputPath.string();
255 auto labelPath =
256 boost::replace_all_copy(inputPathStr, "input", "label");
257 std::ifstream labelFile(labelPath);
258 if (!labelFile.good())
259 {
260 std::cerr << "Failure reading " << labelPath << "\n";
261 continue;
262 }
263 std::string label;
264 std::getline(labelFile, label);
265 labelFile.close();
266 std::string sensorName = label + " CPU" + std::to_string(cpuId);
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700267
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -0800268 auto findSensor = cpuSensors.find(sensorName);
269 if (findSensor != cpuSensors.end())
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700270 {
271 if (DEBUG)
272 {
273 std::cout << "Skipped: " << inputPath << ": " << sensorName
274 << " is already created\n";
275 }
276 continue;
277 }
278
James Feist6714a252018-09-10 15:26:18 -0700279 std::vector<thresholds::Threshold> sensorThresholds;
280 std::string labelHead = label.substr(0, label.find(" "));
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700281 parseThresholdsFromConfig(*sensorData, sensorThresholds,
Yoo, Jae Hyun81a464c2018-10-09 16:38:58 -0700282 &labelHead);
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -0800283 if (sensorThresholds.empty())
James Feist6714a252018-09-10 15:26:18 -0700284 {
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700285 if (!parseThresholdsFromAttr(sensorThresholds, inputPathStr,
286 CPUSensor::sensorScaleFactor))
James Feist6714a252018-09-10 15:26:18 -0700287 {
Yoo, Jae Hyun81a464c2018-10-09 16:38:58 -0700288 std::cerr << "error populating thresholds for "
289 << sensorName << "\n";
James Feist6714a252018-09-10 15:26:18 -0700290 }
291 }
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -0800292 cpuSensors[sensorName] = std::make_unique<CPUSensor>(
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700293 inputPathStr, sensorType, objectServer, dbusConnection, io,
294 sensorName, std::move(sensorThresholds), *interfacePath);
295 createdSensors.insert(sensorName);
James Feist6714a252018-09-10 15:26:18 -0700296 if (DEBUG)
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700297 {
James Feist6714a252018-09-10 15:26:18 -0700298 std::cout << "Mapped: " << inputPath << " to " << sensorName
299 << "\n";
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700300 }
James Feist6714a252018-09-10 15:26:18 -0700301 }
302 }
Yoo, Jae Hyunf78d0a42018-10-10 11:03:11 -0700303
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700304 if (createdSensors.size())
305 {
306 std::cout << "Sensor" << (createdSensors.size() == 1 ? " is" : "s are")
307 << " created\n";
308 }
Yoo, Jae Hyuna441f3c2018-10-09 16:43:03 -0700309
Yoo, Jae Hyunf78d0a42018-10-10 11:03:11 -0700310 return true;
James Feist6714a252018-09-10 15:26:18 -0700311}
312
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700313void exportDevice(const CPUConfig& config)
James Feist6714a252018-09-10 15:26:18 -0700314{
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700315 std::ostringstream hex;
316 hex << std::hex << config.addr;
317 const std::string& addrHexStr = hex.str();
318 std::string busStr = std::to_string(config.bus);
319
320 std::string parameters = "peci-client 0x" + addrHexStr;
321 std::string device = "/sys/bus/peci/devices/peci-" + busStr + "/new_device";
322
James Feistcf3bce62019-01-08 10:07:19 -0800323 std::filesystem::path devicePath(device);
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700324 const std::string& dir = devicePath.parent_path().string();
James Feistcf3bce62019-01-08 10:07:19 -0800325 for (const auto& path : std::filesystem::directory_iterator(dir))
James Feist6714a252018-09-10 15:26:18 -0700326 {
James Feistcf3bce62019-01-08 10:07:19 -0800327 if (!std::filesystem::is_directory(path))
James Feist6714a252018-09-10 15:26:18 -0700328 {
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700329 continue;
James Feist6714a252018-09-10 15:26:18 -0700330 }
331
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700332 const std::string& directoryName = path.path().filename();
333 if (boost::starts_with(directoryName, busStr) &&
334 boost::ends_with(directoryName, addrHexStr))
335 {
336 if (DEBUG)
337 {
338 std::cout << parameters << " on bus " << busStr
339 << " is already exported\n";
340 }
341 return;
342 }
James Feist6714a252018-09-10 15:26:18 -0700343 }
344
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700345 std::ofstream deviceFile(device);
346 if (!deviceFile.good())
James Feist6714a252018-09-10 15:26:18 -0700347 {
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700348 std::cerr << "Error writing " << device << "\n";
James Feist6714a252018-09-10 15:26:18 -0700349 return;
350 }
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700351 deviceFile << parameters;
352 deviceFile.close();
353
354 std::cout << parameters << " on bus " << busStr << " is exported\n";
James Feist6714a252018-09-10 15:26:18 -0700355}
356
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -0800357void detectCpu(
358 boost::asio::deadline_timer& pingTimer,
359 boost::asio::deadline_timer& creationTimer, boost::asio::io_service& io,
360 sdbusplus::asio::object_server& objectServer,
361 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
362 boost::container::flat_map<std::string, std::unique_ptr<CPUSensor>>&
363 cpuSensors,
364 boost::container::flat_set<CPUConfig>& cpuConfigs,
365 ManagedObjectType& sensorConfigs)
James Feist6714a252018-09-10 15:26:18 -0700366{
James Feist6714a252018-09-10 15:26:18 -0700367 size_t rescanDelaySeconds = 0;
368 bool keepPinging = false;
Jae Hyun Yoo9c55e6a2018-10-26 10:09:01 -0700369
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -0800370 for (CPUConfig& config : cpuConfigs)
James Feist6714a252018-09-10 15:26:18 -0700371 {
Jae Hyun Yoo9c55e6a2018-10-26 10:09:01 -0700372 std::string peciDevPath = peciDev + std::to_string(config.bus);
373 auto file = open(peciDevPath.c_str(), O_RDWR | O_CLOEXEC);
374 if (file < 0)
375 {
376 std::cerr << "unable to open " << peciDevPath << "\n";
377 std::exit(EXIT_FAILURE);
378 }
379
James Feist6714a252018-09-10 15:26:18 -0700380 State state;
381 struct peci_ping_msg msg;
382 msg.addr = config.addr;
383 if (!ioctl(file, PECI_IOC_PING, &msg))
384 {
385 bool dimmReady = false;
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700386 for (unsigned int rank = 0; rank < rankNumMax; rank++)
James Feist6714a252018-09-10 15:26:18 -0700387 {
388 struct peci_rd_pkg_cfg_msg msg;
389 msg.addr = config.addr;
390 msg.index = MBX_INDEX_DDR_DIMM_TEMP;
391 msg.param = rank;
392 msg.rx_len = 4;
393 if (!ioctl(file, PECI_IOC_RD_PKG_CFG, &msg))
394 {
395 if (msg.pkg_config[0] || msg.pkg_config[1] ||
396 msg.pkg_config[2])
397 {
398 dimmReady = true;
399 break;
400 }
401 }
402 else
403 {
404 break;
405 }
406 }
Yoo, Jae Hyuna441f3c2018-10-09 16:43:03 -0700407
James Feist6714a252018-09-10 15:26:18 -0700408 if (dimmReady)
409 {
410 state = State::READY;
411 }
412 else
413 {
414 state = State::ON;
415 }
416 }
417 else
418 {
419 state = State::OFF;
420 }
421
Jae Hyun Yoo9c55e6a2018-10-26 10:09:01 -0700422 close(file);
423
James Feist6714a252018-09-10 15:26:18 -0700424 if (config.state != state)
425 {
426 if (config.state == State::OFF)
427 {
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700428 std::cout << config.name << " is detected\n";
429 exportDevice(config);
James Feist6714a252018-09-10 15:26:18 -0700430 }
Yoo, Jae Hyuna441f3c2018-10-09 16:43:03 -0700431 if (state == State::READY)
432 {
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700433 std::cout << "DIMM(s) on " << config.name
Yoo, Jae Hyuna441f3c2018-10-09 16:43:03 -0700434 << " is/are detected\n";
435 }
James Feist6714a252018-09-10 15:26:18 -0700436 config.state = state;
437 }
438
Yoo, Jae Hyunf78d0a42018-10-10 11:03:11 -0700439 if (config.state != State::OFF)
440 {
441 if (config.state == State::ON)
442 {
443 rescanDelaySeconds = 1;
444 }
445 else
446 {
447 rescanDelaySeconds = 5;
448 }
449 }
450
451 if (config.state != State::READY)
James Feist6714a252018-09-10 15:26:18 -0700452 {
453 keepPinging = true;
454 }
455
456 if (DEBUG)
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700457 {
458 std::cout << config.name << ", state: " << config.state << "\n";
459 }
James Feist6714a252018-09-10 15:26:18 -0700460 }
461
James Feist6714a252018-09-10 15:26:18 -0700462 if (rescanDelaySeconds)
463 {
Jae Hyun Yood64262b2018-11-01 13:31:16 -0700464 creationTimer.expires_from_now(
465 boost::posix_time::seconds(rescanDelaySeconds));
466 creationTimer.async_wait([&](const boost::system::error_code& ec) {
467 if (ec == boost::asio::error::operation_aborted)
468 {
469 return; // we're being canceled
470 }
471
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -0800472 if (!createSensors(io, objectServer, dbusConnection, cpuSensors,
473 cpuConfigs, sensorConfigs))
Jae Hyun Yood64262b2018-11-01 13:31:16 -0700474 {
475 detectCpuAsync(pingTimer, creationTimer, io, objectServer,
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -0800476 dbusConnection, cpuSensors, cpuConfigs,
477 sensorConfigs);
Jae Hyun Yood64262b2018-11-01 13:31:16 -0700478 }
479 });
James Feist6714a252018-09-10 15:26:18 -0700480 }
481
482 if (keepPinging)
483 {
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -0800484 detectCpuAsync(pingTimer, creationTimer, io, objectServer,
485 dbusConnection, cpuSensors, cpuConfigs, sensorConfigs);
James Feist6714a252018-09-10 15:26:18 -0700486 }
487}
488
Jae Hyun Yood64262b2018-11-01 13:31:16 -0700489void detectCpuAsync(
490 boost::asio::deadline_timer& pingTimer,
491 boost::asio::deadline_timer& creationTimer, boost::asio::io_service& io,
492 sdbusplus::asio::object_server& objectServer,
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -0800493 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
Jae Hyun Yood64262b2018-11-01 13:31:16 -0700494 boost::container::flat_map<std::string, std::unique_ptr<CPUSensor>>&
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -0800495 cpuSensors,
496 boost::container::flat_set<CPUConfig>& cpuConfigs,
497 ManagedObjectType& sensorConfigs)
Jae Hyun Yood64262b2018-11-01 13:31:16 -0700498{
499 pingTimer.expires_from_now(boost::posix_time::seconds(1));
500 pingTimer.async_wait([&](const boost::system::error_code& ec) {
501 if (ec == boost::asio::error::operation_aborted)
502 {
503 return; // we're being canceled
504 }
505
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -0800506 detectCpu(pingTimer, creationTimer, io, objectServer, dbusConnection,
507 cpuSensors, cpuConfigs, sensorConfigs);
Jae Hyun Yood64262b2018-11-01 13:31:16 -0700508 });
509}
510
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700511bool getCpuConfig(const std::shared_ptr<sdbusplus::asio::connection>& systemBus,
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -0800512 boost::container::flat_set<CPUConfig>& cpuConfigs,
513 ManagedObjectType& sensorConfigs)
James Feist6714a252018-09-10 15:26:18 -0700514{
James Feist6714a252018-09-10 15:26:18 -0700515 bool useCache = false;
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -0800516 sensorConfigs.clear();
James Feist6714a252018-09-10 15:26:18 -0700517 // use new data the first time, then refresh
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700518 for (const char* type : sensorTypes)
James Feist6714a252018-09-10 15:26:18 -0700519 {
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700520 if (!getSensorConfiguration(configPrefix + std::string(type), systemBus,
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -0800521 sensorConfigs, useCache))
James Feist6714a252018-09-10 15:26:18 -0700522 {
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700523 return false;
James Feist6714a252018-09-10 15:26:18 -0700524 }
525 useCache = true;
526 }
527
528 // check PECI client addresses and DT overlay names from CPU configuration
529 // before starting ping operation
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700530 for (const char* type : sensorTypes)
James Feist6714a252018-09-10 15:26:18 -0700531 {
532 for (const std::pair<sdbusplus::message::object_path, SensorData>&
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -0800533 sensor : sensorConfigs)
James Feist6714a252018-09-10 15:26:18 -0700534 {
535 for (const std::pair<
536 std::string,
537 boost::container::flat_map<std::string, BasicVariantType>>&
538 config : sensor.second)
539 {
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700540 if ((configPrefix + std::string(type)) != config.first)
James Feist6714a252018-09-10 15:26:18 -0700541 {
542 continue;
543 }
544
James Feist6714a252018-09-10 15:26:18 -0700545 auto findName = config.second.find("Name");
546 if (findName == config.second.end())
547 {
548 continue;
549 }
James Feist3eb82622019-02-08 13:10:22 -0800550 std::string nameRaw =
551 std::visit(VariantToStringVisitor(), findName->second);
James Feist6714a252018-09-10 15:26:18 -0700552 std::string name =
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700553 std::regex_replace(nameRaw, illegalDbusRegex, "_");
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700554
555 auto findBus = config.second.find("Bus");
556 if (findBus == config.second.end())
557 {
558 std::cerr << "Can't find 'Bus' setting in " << name << "\n";
559 continue;
560 }
James Feist3eb82622019-02-08 13:10:22 -0800561 uint64_t bus =
562 std::visit(VariantToUnsignedIntVisitor(), findBus->second);
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700563
564 auto findAddress = config.second.find("Address");
565 if (findAddress == config.second.end())
566 {
567 std::cerr << "Can't find 'Address' setting in " << name
568 << "\n";
569 continue;
570 }
James Feist3eb82622019-02-08 13:10:22 -0800571 uint64_t addr = std::visit(VariantToUnsignedIntVisitor(),
572 findAddress->second);
James Feist6714a252018-09-10 15:26:18 -0700573
574 if (DEBUG)
575 {
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700576 std::cout << "bus: " << bus << "\n";
James Feist6714a252018-09-10 15:26:18 -0700577 std::cout << "addr: " << addr << "\n";
578 std::cout << "name: " << name << "\n";
579 std::cout << "type: " << type << "\n";
James Feist6714a252018-09-10 15:26:18 -0700580 }
581
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -0800582 cpuConfigs.emplace(bus, addr, name, State::OFF);
James Feist6714a252018-09-10 15:26:18 -0700583 }
584 }
585 }
Yoo, Jae Hyuna441f3c2018-10-09 16:43:03 -0700586
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -0800587 if (cpuConfigs.size())
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700588 {
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -0800589 std::cout << "CPU config" << (cpuConfigs.size() == 1 ? " is" : "s are")
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700590 << " parsed\n";
591 return true;
592 }
593
594 return false;
James Feist6714a252018-09-10 15:26:18 -0700595}
596
597int main(int argc, char** argv)
598{
599 boost::asio::io_service io;
600 auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -0800601 boost::container::flat_set<CPUConfig> cpuConfigs;
James Feist6714a252018-09-10 15:26:18 -0700602
603 systemBus->request_name("xyz.openbmc_project.CPUSensor");
604 sdbusplus::asio::object_server objectServer(systemBus);
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -0800605 boost::container::flat_map<std::string, std::unique_ptr<CPUSensor>>
606 cpuSensors;
James Feist6714a252018-09-10 15:26:18 -0700607 std::vector<std::unique_ptr<sdbusplus::bus::match::match>> matches;
608 boost::asio::deadline_timer pingTimer(io);
Jae Hyun Yood64262b2018-11-01 13:31:16 -0700609 boost::asio::deadline_timer creationTimer(io);
James Feist6714a252018-09-10 15:26:18 -0700610 boost::asio::deadline_timer filterTimer(io);
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -0800611 ManagedObjectType sensorConfigs;
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700612
613 filterTimer.expires_from_now(boost::posix_time::seconds(1));
614 filterTimer.async_wait([&](const boost::system::error_code& ec) {
615 if (ec == boost::asio::error::operation_aborted)
616 {
Jae Hyun Yood64262b2018-11-01 13:31:16 -0700617 return; // we're being canceled
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700618 }
619
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -0800620 if (getCpuConfig(systemBus, cpuConfigs, sensorConfigs))
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700621 {
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -0800622 detectCpuAsync(pingTimer, creationTimer, io, objectServer,
623 systemBus, cpuSensors, cpuConfigs, sensorConfigs);
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700624 }
625 });
626
James Feist6714a252018-09-10 15:26:18 -0700627 std::function<void(sdbusplus::message::message&)> eventHandler =
628 [&](sdbusplus::message::message& message) {
629 if (message.is_method_error())
630 {
631 std::cerr << "callback method error\n";
632 return;
633 }
Jae Hyun Yoo8d9886d2018-10-22 15:24:29 -0700634
635 if (DEBUG)
636 {
637 std::cout << message.get_path() << " is changed\n";
638 }
639
James Feist6714a252018-09-10 15:26:18 -0700640 // this implicitly cancels the timer
641 filterTimer.expires_from_now(boost::posix_time::seconds(1));
James Feist6714a252018-09-10 15:26:18 -0700642 filterTimer.async_wait([&](const boost::system::error_code& ec) {
643 if (ec == boost::asio::error::operation_aborted)
644 {
Jae Hyun Yood64262b2018-11-01 13:31:16 -0700645 return; // we're being canceled
James Feist6714a252018-09-10 15:26:18 -0700646 }
647
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -0800648 if (getCpuConfig(systemBus, cpuConfigs, sensorConfigs))
James Feist6714a252018-09-10 15:26:18 -0700649 {
Jae Hyun Yood64262b2018-11-01 13:31:16 -0700650 detectCpuAsync(pingTimer, creationTimer, io, objectServer,
Jae Hyun Yooe8b60d02019-01-14 15:27:13 -0800651 systemBus, cpuSensors, cpuConfigs,
652 sensorConfigs);
James Feist6714a252018-09-10 15:26:18 -0700653 }
654 });
655 };
656
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700657 for (const char* type : sensorTypes)
James Feist6714a252018-09-10 15:26:18 -0700658 {
659 auto match = std::make_unique<sdbusplus::bus::match::match>(
660 static_cast<sdbusplus::bus::bus&>(*systemBus),
661 "type='signal',member='PropertiesChanged',path_namespace='" +
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700662 std::string(inventoryPath) + "',arg0namespace='" +
663 configPrefix + type + "'",
James Feist6714a252018-09-10 15:26:18 -0700664 eventHandler);
665 matches.emplace_back(std::move(match));
666 }
667
668 io.run();
669}