blob: 34fe1fc7ab0a15870cf8df887a031ba1851cc778 [file] [log] [blame]
Jason M. Billsd1e40602019-05-09 11:43:51 -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
17#include "peci_pcie.hpp"
18
19#include "pciDeviceClass.hpp"
20#include "pciVendors.hpp"
21
Jason M. Billsbce86a62020-10-08 16:03:47 -070022#include <boost/asio/io_service.hpp>
23#include <boost/asio/steady_timer.hpp>
Jason M. Billsd1e40602019-05-09 11:43:51 -070024#include <boost/container/flat_map.hpp>
25#include <boost/container/flat_set.hpp>
26#include <sdbusplus/asio/object_server.hpp>
Jason M. Billsee6d80b2021-06-11 07:37:30 -070027#include <sdbusplus/bus/match.hpp>
Jason M. Billsd1e40602019-05-09 11:43:51 -070028
29#include <iomanip>
30#include <iostream>
31#include <set>
32#include <sstream>
Willy Tu975faf72022-09-23 18:39:16 +000033#include <unordered_set>
Jason M. Billsd1e40602019-05-09 11:43:51 -070034
35namespace peci_pcie
36{
37static boost::container::flat_map<
38 int, boost::container::flat_map<
39 int, boost::container::flat_map<
40 int, std::shared_ptr<sdbusplus::asio::dbus_interface>>>>
41 pcieDeviceDBusMap;
42
Jason M. Billsee6d80b2021-06-11 07:37:30 -070043static bool abortScan;
44
Jason M. Billsd1e40602019-05-09 11:43:51 -070045namespace function
46{
47static constexpr char const* functionTypeName = "FunctionType";
48static constexpr char const* deviceClassName = "DeviceClass";
49static constexpr char const* vendorIdName = "VendorId";
50static constexpr char const* deviceIdName = "DeviceId";
51static constexpr char const* classCodeName = "ClassCode";
52static constexpr char const* revisionIdName = "RevisionId";
53static constexpr char const* subsystemIdName = "SubsystemId";
54static constexpr char const* subsystemVendorIdName = "SubsystemVendorId";
55} // namespace function
Andrei Kartashev6f552032021-05-11 21:25:29 +030056
57static constexpr const std::array pciConfigInfo{
58 std::tuple<const char*, int, int>{function::functionTypeName, -1, -1},
59 std::tuple<const char*, int, int>{function::deviceClassName, -1, -1},
60 std::tuple<const char*, int, int>{function::vendorIdName, 0, 2},
61 std::tuple<const char*, int, int>{function::deviceIdName, 2, 2},
62 std::tuple<const char*, int, int>{function::classCodeName, 9, 3},
63 std::tuple<const char*, int, int>{function::revisionIdName, 8, 1},
64 std::tuple<const char*, int, int>{function::subsystemIdName, 0x2e, 2},
65 std::tuple<const char*, int, int>{function::subsystemVendorIdName, 0x2c,
66 2}};
Jason M. Billsd1e40602019-05-09 11:43:51 -070067} // namespace peci_pcie
68
Andrei Kartashevd570dfd2020-12-16 17:33:16 +030069enum class resCode
70{
71 resOk,
Spencer Kubb5efe72021-09-02 16:11:14 +080072 resSkip,
Andrei Kartashevd570dfd2020-12-16 17:33:16 +030073 resErr
74};
75
Jason M. Bills5d049732019-10-25 15:55:15 -070076struct CPUInfo
Jason M. Billsd1e40602019-05-09 11:43:51 -070077{
Jason M. Bills5d049732019-10-25 15:55:15 -070078 size_t addr;
79 bool skipCpuBuses;
80 boost::container::flat_set<size_t> cpuBusNums;
81};
82
83// PECI Client Address Map
Andrei Kartashev8e966032021-07-02 20:04:30 +030084static resCode getCPUBusMap(std::vector<CPUInfo>& cpuInfo)
Jason M. Bills5d049732019-10-25 15:55:15 -070085{
Andrei Kartashevd570dfd2020-12-16 17:33:16 +030086 cpuInfo.clear();
Andrei Kartashev8e966032021-07-02 20:04:30 +030087 for (size_t addr = MIN_CLIENT_ADDR; addr <= MAX_CLIENT_ADDR; addr++)
Jason M. Billsd1e40602019-05-09 11:43:51 -070088 {
Andrei Kartashev8e966032021-07-02 20:04:30 +030089 if (peci_Ping(addr) != PECI_CC_SUCCESS)
Jason M. Billsd1e40602019-05-09 11:43:51 -070090 {
Andrei Kartashev8e966032021-07-02 20:04:30 +030091 continue;
Jason M. Bills5d049732019-10-25 15:55:15 -070092 }
Jason M. Bills5d049732019-10-25 15:55:15 -070093
Andrei Kartashev8e966032021-07-02 20:04:30 +030094 auto& cpu = cpuInfo.emplace_back(CPUInfo{addr, false, {}});
Jason M. Bills5d049732019-10-25 15:55:15 -070095 uint8_t cc = 0;
96 CPUModel model{};
97 uint8_t stepping = 0;
Andrei Kartashev8e966032021-07-02 20:04:30 +030098 if (peci_GetCPUID(addr, &model, &stepping, &cc) != PECI_CC_SUCCESS)
Jason M. Bills5d049732019-10-25 15:55:15 -070099 {
100 std::cerr << "Cannot get CPUID!\n";
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300101 return resCode::resErr;
Jason M. Bills5d049732019-10-25 15:55:15 -0700102 }
103
104 switch (model)
105 {
106 case skx:
107 {
108 // Get the assigned CPU bus numbers from CPUBUSNO and CPUBUSNO1
109 // (B(0) D8 F2 offsets CCh and D0h)
110 uint32_t cpuBusNum = 0;
Andrei Kartashev8e966032021-07-02 20:04:30 +0300111 if (peci_RdPCIConfigLocal(addr, 0, 8, 2, 0xCC, 4,
Jason M. Bills5d049732019-10-25 15:55:15 -0700112 (uint8_t*)&cpuBusNum,
113 &cc) != PECI_CC_SUCCESS)
114 {
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300115 return resCode::resErr;
Jason M. Bills5d049732019-10-25 15:55:15 -0700116 }
117 uint32_t cpuBusNum1 = 0;
Andrei Kartashev8e966032021-07-02 20:04:30 +0300118 if (peci_RdPCIConfigLocal(addr, 0, 8, 2, 0xD0, 4,
Jason M. Bills5d049732019-10-25 15:55:15 -0700119 (uint8_t*)&cpuBusNum1,
120 &cc) != PECI_CC_SUCCESS)
121 {
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300122 return resCode::resErr;
Jason M. Bills5d049732019-10-25 15:55:15 -0700123 }
124
125 // Add the CPU bus numbers to the set for this CPU
126 while (cpuBusNum)
127 {
128 // Get the LSB
129 size_t busNum = cpuBusNum & 0xFF;
130 cpu.cpuBusNums.insert(busNum);
131 // Shift right by one byte
132 cpuBusNum >>= 8;
133 }
134 while (cpuBusNum1)
135 {
136 // Get the LSB
137 size_t busNum = cpuBusNum1 & 0xFF;
138 cpu.cpuBusNums.insert(busNum);
139 // Shift right by one byte
Zev Weiss9fa54b52020-09-02 21:20:33 +0000140 cpuBusNum1 >>= 8;
Jason M. Bills5d049732019-10-25 15:55:15 -0700141 }
142 cpu.skipCpuBuses = true;
143 }
Jason M. Billsd1e40602019-05-09 11:43:51 -0700144 }
145 }
Andrei Kartashev8e966032021-07-02 20:04:30 +0300146 return cpuInfo.empty() ? resCode::resErr : resCode::resOk;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700147}
148
149static bool isPECIAvailable(void)
150{
Jason M. Bills5d049732019-10-25 15:55:15 -0700151 for (size_t i = MIN_CLIENT_ADDR; i <= MAX_CLIENT_ADDR; i++)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700152 {
Jason M. Bills5d049732019-10-25 15:55:15 -0700153 if (peci_Ping(i) == PECI_CC_SUCCESS)
154 {
155 return true;
156 }
Jason M. Billsd1e40602019-05-09 11:43:51 -0700157 }
Jason M. Bills5d049732019-10-25 15:55:15 -0700158 return false;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700159}
160
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300161static resCode getDataFromPCIeConfig(const int& clientAddr, const int& bus,
162 const int& dev, const int& func,
163 const int& offset, const int& size,
164 uint32_t& pciData)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700165{
166 // PECI RdPCIConfig() currently only supports 4 byte reads, so adjust
167 // the offset and size to get the right data
168 static constexpr const int pciReadSize = 4;
169 int mod = offset % pciReadSize;
170 int pciOffset = offset - mod;
171 if (mod + size > pciReadSize)
172 {
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300173 return resCode::resErr;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700174 }
175
176 std::array<uint8_t, pciReadSize> data;
177 uint8_t cc;
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300178 int ret = PECI_CC_TIMEOUT;
179 for (int index = 0; (index < 5) && (ret == PECI_CC_TIMEOUT); index++)
180 {
Jason M. Bills3b1665a2021-06-11 13:35:04 -0700181#ifdef USE_RDENDPOINTCFG
182 ret = peci_RdEndPointConfigPci(clientAddr, // CPU Address
183 0, // PCI Seg (use 0 for now)
184 bus, // PCI Bus
185 dev, // PCI Device
186 func, // PCI Function
187 pciOffset, // PCI Offset
188 pciReadSize, // PCI Read Size
189 data.data(), // PCI Read Data
190 &cc); // PECI Completion Code
191#else
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300192 ret = peci_RdPCIConfig(clientAddr, // CPU Address
Jason M. Billsd1e40602019-05-09 11:43:51 -0700193 bus, // PCI Bus
194 dev, // PCI Device
195 func, // PCI Function
196 pciOffset, // PCI Offset
197 data.data(), // PCI Read Data
198 &cc); // PECI Completion Code
Jason M. Bills3b1665a2021-06-11 13:35:04 -0700199#endif
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300200 }
Jason M. Billsd1e40602019-05-09 11:43:51 -0700201 if (ret != PECI_CC_SUCCESS || cc != PECI_DEV_CC_SUCCESS)
202 {
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300203 return resCode::resErr;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700204 }
205
206 // Now build the requested data into a single number
207 pciData = 0;
208 for (int i = mod; i < mod + size; i++)
209 {
Jason M. Billse55832b2021-06-14 16:00:49 -0700210 pciData |= static_cast<uint32_t>(data[i]) << 8 * (i - mod);
Jason M. Billsd1e40602019-05-09 11:43:51 -0700211 }
212
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300213 return resCode::resOk;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700214}
215
Andrei Kartashev6f552032021-05-11 21:25:29 +0300216static resCode getStringFromData(const int& size, const uint32_t& data,
217 std::string& res)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700218{
Jason M. Billsd1e40602019-05-09 11:43:51 -0700219 // And convert it to a string
220 std::stringstream dataStream;
221 dataStream << "0x" << std::hex << std::setfill('0') << std::setw(size * 2)
222 << data;
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300223 res = dataStream.str();
224 return resCode::resOk;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700225}
226
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300227static resCode getVendorName(const int& clientAddr, const int& bus,
228 const int& dev, std::string& res)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700229{
230 static constexpr const int vendorIDOffset = 0x00;
231 static constexpr const int vendorIDSize = 2;
232
233 // Get the header type register from function 0
234 uint32_t vendorID = 0;
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300235 if (getDataFromPCIeConfig(clientAddr, bus, dev, 0, vendorIDOffset,
236 vendorIDSize, vendorID) != resCode::resOk)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700237 {
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300238 return resCode::resErr;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700239 }
240 // Get the vendor name or use Other if it doesn't exist
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300241 res = pciVendors.try_emplace(vendorID, otherVendor).first->second;
242 return resCode::resOk;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700243}
244
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300245static resCode getDeviceClass(const int& clientAddr, const int& bus,
246 const int& dev, const int& func, std::string& res)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700247{
248 static constexpr const int baseClassOffset = 0x0b;
249 static constexpr const int baseClassSize = 1;
250
251 // Get the Device Base Class
252 uint32_t baseClass = 0;
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300253 if (getDataFromPCIeConfig(clientAddr, bus, dev, func, baseClassOffset,
254 baseClassSize, baseClass) != resCode::resOk)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700255 {
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300256 return resCode::resErr;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700257 }
258 // Get the base class name or use Other if it doesn't exist
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300259 res = pciDeviceClasses.try_emplace(baseClass, otherClass).first->second;
260 return resCode::resOk;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700261}
262
Spencer Kubb5efe72021-09-02 16:11:14 +0800263static resCode getCapReading(const int& clientAddr, const int& bus,
264 const int& dev, uint32_t& capReading,
265 const int compareCapID, const int offsetAddress,
266 const int offsetLength)
267{
268 resCode error;
269 uint32_t capAddress = 0;
270 uint32_t capabilityID;
271 uint32_t nextCapPointer = peci_pcie::pointToCapStruct;
272
273 do
274 {
275 // Get capability address
276 error = getDataFromPCIeConfig(clientAddr, bus, dev, 0, nextCapPointer,
277 1, capAddress);
278 if (error != resCode::resOk)
279 {
280 return error;
281 }
282 // Capability struct address is a pointer which point to next capability
283 // struct, so if capability struct address is 0 means it doesn't have
284 // next capability struct.
285 if (capAddress == 0)
286 {
287 return resCode::resSkip;
288 }
289 // Get capability ID
290 error = getDataFromPCIeConfig(clientAddr, bus, dev, 0, capAddress, 1,
291 capabilityID);
292 if (error != resCode::resOk)
293 {
294 return error;
295 }
296 nextCapPointer = capAddress + peci_pcie::capPointerOffset;
297
298 } while (capabilityID != compareCapID);
299 // Get capability reading.
300 error = getDataFromPCIeConfig(clientAddr, bus, dev, 0,
301 capAddress + offsetAddress, offsetLength,
302 capReading);
303 if (error != resCode::resOk)
304 {
305 return error;
306 }
307 return resCode::resOk;
308}
309
310static resCode getGenerationInUse(const int& clientAddr, const int& bus,
311 const int& dev, std::string& generationInUse)
312{
Willy Tu975faf72022-09-23 18:39:16 +0000313 static std::unordered_set<uint32_t> linkSpeedSkipMap;
Spencer Kubb5efe72021-09-02 16:11:14 +0800314 resCode error;
315 std::string res;
316 uint32_t capReading = 0;
317
318 // Capability ID 0x10(16) is PCI Express
319 constexpr int pcieCapID = 16;
320 constexpr int capLength = 2;
321 uint32_t linkStatus;
322
323 error = getCapReading(clientAddr, bus, dev, linkStatus, pcieCapID,
324 peci_pcie::linkStatusOffset, capLength);
325 if (error != resCode::resOk)
326 {
327 return error;
328 }
329
330 uint32_t linkSpeed = linkStatus & peci_pcie::maskOfCLS;
331
332 switch (linkSpeed)
333 {
334 case peci_pcie::pcieGen1:
335 generationInUse = "xyz.openbmc_project.Inventory.Item."
336 "PCIeSlot.Generations.Gen1";
337 error = resCode::resOk;
338 break;
339 case peci_pcie::pcieGen2:
340 generationInUse = "xyz.openbmc_project.Inventory.Item."
341 "PCIeSlot.Generations.Gen2";
342 error = resCode::resOk;
343 break;
344 case peci_pcie::pcieGen3:
345 generationInUse = "xyz.openbmc_project.Inventory.Item."
346 "PCIeSlot.Generations.Gen3";
347 error = resCode::resOk;
348 break;
349 case peci_pcie::pcieGen4:
350 generationInUse = "xyz.openbmc_project.Inventory.Item."
351 "PCIeSlot.Generations.Gen4";
352 error = resCode::resOk;
353 break;
354 case peci_pcie::pcieGen5:
355 generationInUse = "xyz.openbmc_project.Inventory.Item."
356 "PCIeSlot.Generations.Gen5";
357 error = resCode::resOk;
358 break;
359 default:
Willy Tu975faf72022-09-23 18:39:16 +0000360 if (!linkSpeedSkipMap.contains(linkSpeed))
361 {
362 std::cerr << "Link speed : " << linkSpeed
363 << " can not mapping to PCIe type list.\n";
364 linkSpeedSkipMap.emplace(linkSpeed);
365 }
Spencer Kubb5efe72021-09-02 16:11:14 +0800366 error = resCode::resSkip;
367 }
368 return error;
369}
370
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300371static resCode isMultiFunction(const int& clientAddr, const int& bus,
372 const int& dev, bool& res)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700373{
374 static constexpr const int headerTypeOffset = 0x0e;
375 static constexpr const int headerTypeSize = 1;
376 static constexpr const int multiFuncBit = 1 << 7;
377
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300378 res = false;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700379 // Get the header type register from function 0
380 uint32_t headerType = 0;
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300381 if (getDataFromPCIeConfig(clientAddr, bus, dev, 0, headerTypeOffset,
382 headerTypeSize, headerType) != resCode::resOk)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700383 {
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300384 return resCode::resErr;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700385 }
386 // Check if it's a multifunction device
387 if (headerType & multiFuncBit)
388 {
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300389 res = true;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700390 }
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300391 return resCode::resOk;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700392}
393
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300394static resCode pcieFunctionExists(const int& clientAddr, const int& bus,
395 const int& dev, const int& func, bool& res)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700396{
397 constexpr const int pciIDOffset = 0;
398 constexpr const int pciIDSize = 4;
399 uint32_t pciID = 0;
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300400 res = false;
401 if (getDataFromPCIeConfig(clientAddr, bus, dev, func, pciIDOffset,
402 pciIDSize, pciID) != resCode::resOk)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700403 {
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300404 return resCode::resOk;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700405 }
406
407 // if VID and DID are all 0s or 1s, then the device doesn't exist
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300408 if (pciID != 0x00000000 && pciID != 0xFFFFFFFF)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700409 {
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300410 res = true;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700411 }
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300412 return resCode::resOk;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700413}
414
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300415static resCode pcieDeviceExists(const int& clientAddr, const int& bus,
416 const int& dev, bool& res)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700417{
418 // Check if this device exists by checking function 0
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300419 return pcieFunctionExists(clientAddr, bus, dev, 0, res);
Jason M. Billsd1e40602019-05-09 11:43:51 -0700420}
421
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300422static resCode setPCIeProperty(const int& clientAddr, const int& bus,
423 const int& dev, const std::string& propertyName,
424 const std::string& propertyValue)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700425{
426 std::shared_ptr<sdbusplus::asio::dbus_interface> iface =
427 peci_pcie::pcieDeviceDBusMap[clientAddr][bus][dev];
428
429 if (iface->is_initialized())
430 {
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300431 if (!iface->set_property(propertyName, propertyValue))
432 return resCode::resErr;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700433 }
434 else
435 {
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300436 if (!iface->register_property(propertyName, propertyValue))
437 return resCode::resErr;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700438 }
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300439 return resCode::resOk;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700440}
441
442static void setDefaultPCIeFunctionProperties(const int& clientAddr,
443 const int& bus, const int& dev,
444 const int& func)
445{
446 // Set the function-specific properties
Andrei Kartashev6f552032021-05-11 21:25:29 +0300447 for (const auto& [name, offset, size] : peci_pcie::pciConfigInfo)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700448 {
449 setPCIeProperty(clientAddr, bus, dev,
450 "Function" + std::to_string(func) + std::string(name),
451 std::string());
452 }
453}
454
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300455static resCode setPCIeFunctionProperties(const int& clientAddr, const int& bus,
456 const int& dev, const int& func)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700457{
Andrei Kartashev6f552032021-05-11 21:25:29 +0300458 uint32_t data = 0;
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300459 std::string res;
Andrei Kartashev6f552032021-05-11 21:25:29 +0300460 resCode error;
461
462 for (const auto& [name, offset, size] : peci_pcie::pciConfigInfo)
463 {
464 if (offset < 0)
465 {
466 continue;
467 }
468
469 error = getDataFromPCIeConfig(clientAddr, bus, dev, func, offset, size,
470 data);
471 if (error != resCode::resOk)
472 {
473 return error;
474 }
475 getStringFromData(size, data, res);
476 setPCIeProperty(clientAddr, bus, dev,
477 "Function" + std::to_string(func) + std::string(name),
478 res);
479 }
480
Jason M. Billsd1e40602019-05-09 11:43:51 -0700481 // Set the function type always to physical for now
482 setPCIeProperty(clientAddr, bus, dev,
483 "Function" + std::to_string(func) +
484 std::string(peci_pcie::function::functionTypeName),
485 "Physical");
486
487 // Set the function Device Class
Andrei Kartashev6f552032021-05-11 21:25:29 +0300488 error = getDeviceClass(clientAddr, bus, dev, func, res);
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300489 if (error != resCode::resOk)
490 {
491 return error;
492 }
Jason M. Billsd1e40602019-05-09 11:43:51 -0700493 setPCIeProperty(clientAddr, bus, dev,
494 "Function" + std::to_string(func) +
495 std::string(peci_pcie::function::deviceClassName),
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300496 res);
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300497 return resCode::resOk;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700498}
499
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300500static resCode setPCIeDeviceProperties(const int& clientAddr, const int& bus,
501 const int& dev)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700502{
503 // Set the device manufacturer
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300504 std::string manuf;
505 resCode error = getVendorName(clientAddr, bus, dev, manuf);
506 if (error != resCode::resOk)
507 {
508 return error;
509 }
510 setPCIeProperty(clientAddr, bus, dev, "Manufacturer", manuf);
Jason M. Billsd1e40602019-05-09 11:43:51 -0700511
512 // Set the device type
513 constexpr char const* deviceTypeName = "DeviceType";
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300514 bool multiFunc;
515 error = isMultiFunction(clientAddr, bus, dev, multiFunc);
516 if (error != resCode::resOk)
517 {
518 return error;
519 }
520 if (multiFunc)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700521 {
522 setPCIeProperty(clientAddr, bus, dev, deviceTypeName, "MultiFunction");
523 }
524 else
525 {
526 setPCIeProperty(clientAddr, bus, dev, deviceTypeName, "SingleFunction");
527 }
Spencer Kubb5efe72021-09-02 16:11:14 +0800528
529 // Set PCIe Generation
530 constexpr char const* generationInUseName = "GenerationInUse";
531 std::string generationInUse;
532 error = getGenerationInUse(clientAddr, bus, dev, generationInUse);
533 if (error == resCode::resErr)
534 {
535 return error;
536 }
537 // "resSkip" status means it can't get the capability reading, such like
538 // this device is not PCI Express.
539 if (error == resCode::resSkip)
540 {
541 setPCIeProperty(clientAddr, bus, dev, generationInUseName, "");
542 return resCode::resOk;
543 }
544 setPCIeProperty(clientAddr, bus, dev, generationInUseName, generationInUse);
545
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300546 return resCode::resOk;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700547}
548
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300549static resCode updatePCIeDevice(const int& clientAddr, const int& bus,
550 const int& dev)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700551{
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300552 if (setPCIeDeviceProperties(clientAddr, bus, dev) != resCode::resOk)
553 {
554 return resCode::resErr;
555 }
Jason M. Billsd1e40602019-05-09 11:43:51 -0700556
557 // Walk through and populate the functions for this device
558 for (int func = 0; func < peci_pcie::maxPCIFunctions; func++)
559 {
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300560 bool res;
561 resCode error = pcieFunctionExists(clientAddr, bus, dev, func, res);
562 if (error != resCode::resOk)
563 {
564 return error;
565 }
566 if (res)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700567 {
568 // Set the properties for this function
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300569 if (setPCIeFunctionProperties(clientAddr, bus, dev, func) !=
570 resCode::resOk)
571 {
572 return resCode::resErr;
573 }
Jason M. Billsd1e40602019-05-09 11:43:51 -0700574 }
575 else
576 {
577 // Set default properties for unused functions
578 setDefaultPCIeFunctionProperties(clientAddr, bus, dev, func);
579 }
580 }
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300581 return resCode::resOk;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700582}
583
584static void removePCIeDevice(sdbusplus::asio::object_server& objServer,
585 const int& clientAddr, const int& bus,
586 const int& dev)
587{
588 std::shared_ptr<sdbusplus::asio::dbus_interface> iface =
589 peci_pcie::pcieDeviceDBusMap[clientAddr][bus][dev];
590
591 objServer.remove_interface(iface);
592
593 peci_pcie::pcieDeviceDBusMap[clientAddr][bus].erase(dev);
594 if (peci_pcie::pcieDeviceDBusMap[clientAddr][bus].empty())
595 {
596 peci_pcie::pcieDeviceDBusMap[clientAddr].erase(bus);
597 }
598 if (peci_pcie::pcieDeviceDBusMap[clientAddr].empty())
599 {
600 peci_pcie::pcieDeviceDBusMap.erase(clientAddr);
601 }
602}
603
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300604static resCode addPCIeDevice(sdbusplus::asio::object_server& objServer,
605 const int& clientAddr, const int& cpu,
606 const int& bus, const int& dev)
607{
608 std::string pathName = std::string(peci_pcie::peciPCIePath) + "/S" +
609 std::to_string(cpu) + "B" + std::to_string(bus) +
610 "D" + std::to_string(dev);
611 std::shared_ptr<sdbusplus::asio::dbus_interface> iface =
612 objServer.add_interface(pathName, peci_pcie::peciPCIeDeviceInterface);
613 peci_pcie::pcieDeviceDBusMap[clientAddr][bus][dev] = iface;
614
615 // Update the properties for the new device
616 if (updatePCIeDevice(clientAddr, bus, dev) != resCode::resOk)
617 {
618 removePCIeDevice(objServer, clientAddr, bus, dev);
619 return resCode::resErr;
620 }
621
622 iface->initialize();
623 return resCode::resOk;
624}
625
Jason M. Billsd1e40602019-05-09 11:43:51 -0700626static bool pcieDeviceInDBusMap(const int& clientAddr, const int& bus,
627 const int& dev)
628{
629 if (auto clientAddrIt = peci_pcie::pcieDeviceDBusMap.find(clientAddr);
630 clientAddrIt != peci_pcie::pcieDeviceDBusMap.end())
631 {
632 if (auto busIt = clientAddrIt->second.find(bus);
633 busIt != clientAddrIt->second.end())
634 {
635 if (auto devIt = busIt->second.find(dev);
636 devIt != busIt->second.end())
637 {
638 if (devIt->second)
639 {
640 return true;
641 }
642 }
643 }
644 }
645 return false;
646}
647
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300648static resCode probePCIeDevice(boost::asio::io_service& io,
649 sdbusplus::asio::object_server& objServer,
Andrei Kartashev8e966032021-07-02 20:04:30 +0300650 size_t addr, int cpu, int bus, int dev)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700651{
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300652 bool res;
Andrei Kartashev8e966032021-07-02 20:04:30 +0300653 resCode error = pcieDeviceExists(addr, bus, dev, res);
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300654 if (error != resCode::resOk)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700655 {
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300656 return error;
Jason M. Bills5d049732019-10-25 15:55:15 -0700657 }
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300658 if (res)
Jason M. Bills5d049732019-10-25 15:55:15 -0700659 {
Andrei Kartashev8e966032021-07-02 20:04:30 +0300660 if (pcieDeviceInDBusMap(addr, bus, dev))
Jason M. Billsd1e40602019-05-09 11:43:51 -0700661 {
662 // This device is already in D-Bus, so update it
Andrei Kartashev8e966032021-07-02 20:04:30 +0300663 if (updatePCIeDevice(addr, bus, dev) != resCode::resOk)
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300664 {
665 return resCode::resErr;
666 }
Jason M. Billsd1e40602019-05-09 11:43:51 -0700667 }
668 else
669 {
670 // This device is not in D-Bus, so add it
Andrei Kartashev8e966032021-07-02 20:04:30 +0300671 if (addPCIeDevice(objServer, addr, cpu, bus, dev) != resCode::resOk)
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300672 {
673 return resCode::resErr;
674 }
Jason M. Billsd1e40602019-05-09 11:43:51 -0700675 }
676 }
677 else
678 {
679 // If PECI is not available, then stop scanning
680 if (!isPECIAvailable())
681 {
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300682 return resCode::resOk;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700683 }
684
Andrei Kartashev8e966032021-07-02 20:04:30 +0300685 if (pcieDeviceInDBusMap(addr, bus, dev))
Jason M. Billsd1e40602019-05-09 11:43:51 -0700686 {
687 // This device is in D-Bus, so remove it
Andrei Kartashev8e966032021-07-02 20:04:30 +0300688 removePCIeDevice(objServer, addr, bus, dev);
Jason M. Billsd1e40602019-05-09 11:43:51 -0700689 }
690 }
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300691 return resCode::resOk;
692}
693
Andrei Kartashev8e966032021-07-02 20:04:30 +0300694static void scanNextPCIeDevice(boost::asio::io_service& io,
695 sdbusplus::asio::object_server& objServer,
696 std::vector<CPUInfo>& cpuInfo, int cpu, int bus,
697 int dev);
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300698static void scanPCIeDevice(boost::asio::io_service& io,
699 sdbusplus::asio::object_server& objServer,
700 std::vector<CPUInfo>& cpuInfo, int cpu, int bus,
701 int dev)
702{
Andrei Kartashev8e966032021-07-02 20:04:30 +0300703 if (cpu >= cpuInfo.size())
704 {
705 std::cerr << "Request to scan CPU" << cpu
706 << " while CPU array has size " << cpuInfo.size() << "\n";
707 return;
708 }
709 auto& info = cpuInfo[cpu];
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300710 // Check if this is a CPU bus that we should skip
Andrei Kartashev8e966032021-07-02 20:04:30 +0300711 if (info.skipCpuBuses && info.cpuBusNums.count(bus))
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300712 {
713 std::cout << "Skipping CPU " << cpu << " Bus Number " << bus << "\n";
714 // Skip all the devices on this bus
715 dev = peci_pcie::maxPCIDevices;
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300716 }
Andrei Kartashev8e966032021-07-02 20:04:30 +0300717 else
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300718 {
Andrei Kartashev8e966032021-07-02 20:04:30 +0300719 if (probePCIeDevice(io, objServer, info.addr, cpu, bus, dev) !=
720 resCode::resOk)
721 {
722 std::cerr << "Failed to probe CPU " << cpu << " Bus " << bus
723 << " Device " << dev << "\n";
724 }
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300725 }
726
Jason M. Bills5d049732019-10-25 15:55:15 -0700727 scanNextPCIeDevice(io, objServer, cpuInfo, cpu, bus, dev);
Andrei Kartashev8e966032021-07-02 20:04:30 +0300728 return;
Jason M. Bills5d049732019-10-25 15:55:15 -0700729}
Jason M. Billsd1e40602019-05-09 11:43:51 -0700730
Jason M. Bills5d049732019-10-25 15:55:15 -0700731static void scanNextPCIeDevice(boost::asio::io_service& io,
732 sdbusplus::asio::object_server& objServer,
733 std::vector<CPUInfo>& cpuInfo, int cpu, int bus,
734 int dev)
735{
Jason M. Billsee6d80b2021-06-11 07:37:30 -0700736 if (peci_pcie::abortScan)
737 {
738 std::cerr << "PCIe scan aborted\n";
739 return;
740 }
741
Jason M. Billsd1e40602019-05-09 11:43:51 -0700742 // PCIe Device scan completed, so move to the next device
743 if (++dev >= peci_pcie::maxPCIDevices)
744 {
745 // All devices scanned, so move to the next bus
746 dev = 0;
747 if (++bus >= peci_pcie::maxPCIBuses)
748 {
749 // All buses scanned, so move to the next CPU
750 bus = 0;
Jason M. Bills5d049732019-10-25 15:55:15 -0700751 if (++cpu >= cpuInfo.size())
Jason M. Billsd1e40602019-05-09 11:43:51 -0700752 {
753 // All CPUs scanned, so we're done
Jason M. Billsee6d80b2021-06-11 07:37:30 -0700754 std::cerr << "PCIe scan completed\n";
Jason M. Billsd1e40602019-05-09 11:43:51 -0700755 return;
756 }
757 }
758 }
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300759 boost::asio::post(io, [&io, &objServer, &cpuInfo, cpu, bus, dev]() mutable {
Jason M. Bills5d049732019-10-25 15:55:15 -0700760 scanPCIeDevice(io, objServer, cpuInfo, cpu, bus, dev);
Jason M. Billsd1e40602019-05-09 11:43:51 -0700761 });
762}
763
764static void peciAvailableCheck(boost::asio::steady_timer& peciWaitTimer,
765 boost::asio::io_service& io,
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300766 sdbusplus::asio::object_server& objServer,
767 std::vector<CPUInfo>& cpuInfo)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700768{
Jason M. Bills5d049732019-10-25 15:55:15 -0700769 static bool lastPECIState = false;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700770 bool peciAvailable = isPECIAvailable();
771 if (peciAvailable && !lastPECIState)
772 {
773 lastPECIState = true;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700774 static boost::asio::steady_timer pcieTimeout(io);
775 constexpr const int pcieWaitTime = 60;
776 pcieTimeout.expires_after(std::chrono::seconds(pcieWaitTime));
777 pcieTimeout.async_wait(
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300778 [&io, &objServer, &cpuInfo](const boost::system::error_code& ec) {
Jason M. Billsd1e40602019-05-09 11:43:51 -0700779 if (ec)
780 {
781 // operation_aborted is expected if timer is canceled
782 // before completion.
783 if (ec != boost::asio::error::operation_aborted)
784 {
785 std::cerr << "PECI PCIe async_wait failed " << ec;
786 }
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300787 lastPECIState = false;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700788 return;
789 }
790 // get the PECI client address list
Andrei Kartashev8e966032021-07-02 20:04:30 +0300791 if (getCPUBusMap(cpuInfo) != resCode::resOk)
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300792 {
793 lastPECIState = false;
794 return;
795 }
Jason M. Billsd1e40602019-05-09 11:43:51 -0700796 // scan PCIe starting from CPU 0, Bus 0, Device 0
Jason M. Billsee6d80b2021-06-11 07:37:30 -0700797 std::cerr << "PCIe scan started\n";
Jason M. Bills5d049732019-10-25 15:55:15 -0700798 scanPCIeDevice(io, objServer, cpuInfo, 0, 0, 0);
Jason M. Billsd1e40602019-05-09 11:43:51 -0700799 });
800 }
801 else if (!peciAvailable && lastPECIState)
802 {
803 lastPECIState = false;
804 }
805
806 peciWaitTimer.expires_after(
807 std::chrono::seconds(peci_pcie::peciCheckInterval));
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300808 peciWaitTimer.async_wait([&peciWaitTimer, &io, &objServer,
809 &cpuInfo](const boost::system::error_code& ec) {
Jason M. Billsd1e40602019-05-09 11:43:51 -0700810 if (ec)
811 {
812 // operation_aborted is expected if timer is canceled
813 // before completion.
814 if (ec != boost::asio::error::operation_aborted)
815 {
816 std::cerr << "PECI Available Check async_wait failed " << ec;
817 }
818 return;
819 }
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300820 peciAvailableCheck(peciWaitTimer, io, objServer, cpuInfo);
Jason M. Billsd1e40602019-05-09 11:43:51 -0700821 });
822}
823
Jason M. Billsee6d80b2021-06-11 07:37:30 -0700824static void waitForOSStandbyDelay(boost::asio::io_service& io,
825 sdbusplus::asio::object_server& objServer,
826 boost::asio::steady_timer& osStandbyTimer,
827 std::vector<CPUInfo>& cpuInfo)
828{
829 osStandbyTimer.expires_after(
830 std::chrono::seconds(peci_pcie::osStandbyDelaySeconds));
831
832 osStandbyTimer.async_wait(
833 [&io, &objServer, &cpuInfo](const boost::system::error_code& ec) {
834 if (ec == boost::asio::error::operation_aborted)
835 {
836 return; // we're being canceled
837 }
838 else if (ec)
839 {
840 std::cerr << "OS Standby async_wait failed: " << ec.value()
841 << ": " << ec.message() << "\n";
842 return;
843 }
844 // get the PECI client address list
Andrei Kartashev8e966032021-07-02 20:04:30 +0300845 if (getCPUBusMap(cpuInfo) != resCode::resOk)
Jason M. Billsee6d80b2021-06-11 07:37:30 -0700846 {
847 return;
848 }
849 // scan PCIe starting from CPU 0, Bus 0, Device 0
850 std::cerr << "PCIe scan started\n";
851 scanPCIeDevice(io, objServer, cpuInfo, 0, 0, 0);
852 });
853}
854
855static void monitorOSStandby(boost::asio::io_service& io,
856 std::shared_ptr<sdbusplus::asio::connection> conn,
857 sdbusplus::asio::object_server& objServer,
858 boost::asio::steady_timer& osStandbyTimer,
859 std::vector<CPUInfo>& cpuInfo)
860{
861 std::cerr << "Start OperatingSystemState Monitor\n";
862
Patrick Williamsb2517082022-07-22 19:26:57 -0500863 static sdbusplus::bus::match_t osStateMatch(
Jason M. Billsee6d80b2021-06-11 07:37:30 -0700864 *conn,
865 "type='signal',interface='org.freedesktop.DBus.Properties',member='"
866 "PropertiesChanged',arg0='xyz.openbmc_project.State.OperatingSystem."
867 "Status'",
868 [&io, &objServer, &osStandbyTimer,
Patrick Williamsb2517082022-07-22 19:26:57 -0500869 &cpuInfo](sdbusplus::message_t& msg) {
Jason M. Billsee6d80b2021-06-11 07:37:30 -0700870 // Get the OS State from the message
871 std::string osStateInterface;
872 boost::container::flat_map<std::string, std::variant<std::string>>
873 propertiesChanged;
874 msg.read(osStateInterface, propertiesChanged);
875
876 for (const auto& [name, value] : propertiesChanged)
877 {
878 if (name == "OperatingSystemState")
879 {
880 const std::string* state = std::get_if<std::string>(&value);
881 if (state == nullptr)
882 {
883 std::cerr << "Unable to read OS state value\n";
884 return;
885 }
Andrei Kartashev328685e2021-12-27 17:24:18 +0300886 // Note: Short version of OperatingSystemState value is
887 // deprecated and would be removed in the future
888 if ((*state == "Standby") ||
889 (*state == "xyz.openbmc_project.State.OperatingSystem."
890 "Status.OSStatus.Standby"))
Jason M. Billsee6d80b2021-06-11 07:37:30 -0700891 {
892 peci_pcie::abortScan = false;
893 waitForOSStandbyDelay(io, objServer, osStandbyTimer,
894 cpuInfo);
895 }
Andrei Kartashev328685e2021-12-27 17:24:18 +0300896 else if ((*state == "Inactive") ||
897 (*state ==
898 "xyz.openbmc_project.State.OperatingSystem."
899 "Status.OSStatus.Inactive"))
Jason M. Billsee6d80b2021-06-11 07:37:30 -0700900 {
901 peci_pcie::abortScan = true;
902 osStandbyTimer.cancel();
903 }
904 }
905 }
906 });
907
908 // Check if the OS state is already available
909 conn->async_method_call(
910 [&io, &objServer, &osStandbyTimer,
911 &cpuInfo](boost::system::error_code ec,
912 const std::variant<std::string>& property) {
913 if (ec)
914 {
915 std::cerr << "error with OS state async_method_call\n";
916 return;
917 }
918
919 const std::string* state = std::get_if<std::string>(&property);
920 if (state == nullptr)
921 {
922 std::cerr << "Unable to read OS state value\n";
923 return;
924 }
925
926 // If the OS state is in Standby, then BIOS is done and we can
927 // continue. Otherwise, we just wait for the match
Andrei Kartashev328685e2021-12-27 17:24:18 +0300928 // Note: Short version of OperatingSystemState value is deprecated
929 // and would be removed in the future
930
931 if ((*state == "Standby") ||
932 (*state == "xyz.openbmc_project.State.OperatingSystem.Status."
933 "OSStatus.Standby"))
Jason M. Billsee6d80b2021-06-11 07:37:30 -0700934 {
935 waitForOSStandbyDelay(io, objServer, osStandbyTimer, cpuInfo);
936 }
937 },
938 "xyz.openbmc_project.State.OperatingSystem",
939 "/xyz/openbmc_project/state/os", "org.freedesktop.DBus.Properties",
940 "Get", "xyz.openbmc_project.State.OperatingSystem.Status",
941 "OperatingSystemState");
942}
943
Jason M. Billsd1e40602019-05-09 11:43:51 -0700944int main(int argc, char* argv[])
945{
946 // setup connection to dbus
947 boost::asio::io_service io;
948 std::shared_ptr<sdbusplus::asio::connection> conn =
949 std::make_shared<sdbusplus::asio::connection>(io);
950
951 // PECI PCIe Object
952 conn->request_name(peci_pcie::peciPCIeObject);
953 sdbusplus::asio::object_server server =
954 sdbusplus::asio::object_server(conn);
955
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300956 // CPU map
957 std::vector<CPUInfo> cpuInfo;
958
Jason M. Billsee6d80b2021-06-11 07:37:30 -0700959#ifdef WAIT_FOR_OS_STANDBY
960 boost::asio::steady_timer osStandbyTimer(io);
961 monitorOSStandby(io, conn, server, osStandbyTimer, cpuInfo);
962#else
Jason M. Billsd1e40602019-05-09 11:43:51 -0700963 // Start the PECI check loop
964 boost::asio::steady_timer peciWaitTimer(
965 io, std::chrono::seconds(peci_pcie::peciCheckInterval));
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300966 peciWaitTimer.async_wait([&peciWaitTimer, &io, &server,
967 &cpuInfo](const boost::system::error_code& ec) {
Jason M. Billsd1e40602019-05-09 11:43:51 -0700968 if (ec)
969 {
970 // operation_aborted is expected if timer is canceled
971 // before completion.
972 if (ec != boost::asio::error::operation_aborted)
973 {
974 std::cerr << "PECI Available Check async_wait failed " << ec;
975 }
976 return;
977 }
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300978 peciAvailableCheck(peciWaitTimer, io, server, cpuInfo);
Jason M. Billsd1e40602019-05-09 11:43:51 -0700979 });
Jason M. Billsee6d80b2021-06-11 07:37:30 -0700980#endif
Jason M. Billsd1e40602019-05-09 11:43:51 -0700981
982 io.run();
983
984 return 0;
985}