blob: 312e339c08a6694edc7334c1fa1bf9ff24bc8343 [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;
Paul Fertser07343142022-12-01 21:04:57 +000044static bool scanInProgress;
Jason M. Billsee6d80b2021-06-11 07:37:30 -070045
Jason M. Billsd1e40602019-05-09 11:43:51 -070046namespace function
47{
48static constexpr char const* functionTypeName = "FunctionType";
49static constexpr char const* deviceClassName = "DeviceClass";
50static constexpr char const* vendorIdName = "VendorId";
51static constexpr char const* deviceIdName = "DeviceId";
52static constexpr char const* classCodeName = "ClassCode";
53static constexpr char const* revisionIdName = "RevisionId";
54static constexpr char const* subsystemIdName = "SubsystemId";
55static constexpr char const* subsystemVendorIdName = "SubsystemVendorId";
56} // namespace function
Andrei Kartashev6f552032021-05-11 21:25:29 +030057
58static constexpr const std::array pciConfigInfo{
59 std::tuple<const char*, int, int>{function::functionTypeName, -1, -1},
60 std::tuple<const char*, int, int>{function::deviceClassName, -1, -1},
61 std::tuple<const char*, int, int>{function::vendorIdName, 0, 2},
62 std::tuple<const char*, int, int>{function::deviceIdName, 2, 2},
63 std::tuple<const char*, int, int>{function::classCodeName, 9, 3},
64 std::tuple<const char*, int, int>{function::revisionIdName, 8, 1},
65 std::tuple<const char*, int, int>{function::subsystemIdName, 0x2e, 2},
66 std::tuple<const char*, int, int>{function::subsystemVendorIdName, 0x2c,
67 2}};
Jason M. Billsd1e40602019-05-09 11:43:51 -070068} // namespace peci_pcie
69
Andrei Kartashevd570dfd2020-12-16 17:33:16 +030070enum class resCode
71{
72 resOk,
Spencer Kubb5efe72021-09-02 16:11:14 +080073 resSkip,
Andrei Kartashevd570dfd2020-12-16 17:33:16 +030074 resErr
75};
76
Jason M. Bills5d049732019-10-25 15:55:15 -070077struct CPUInfo
Jason M. Billsd1e40602019-05-09 11:43:51 -070078{
Jason M. Bills5d049732019-10-25 15:55:15 -070079 size_t addr;
80 bool skipCpuBuses;
81 boost::container::flat_set<size_t> cpuBusNums;
82};
83
84// PECI Client Address Map
Andrei Kartashev8e966032021-07-02 20:04:30 +030085static resCode getCPUBusMap(std::vector<CPUInfo>& cpuInfo)
Jason M. Bills5d049732019-10-25 15:55:15 -070086{
Andrei Kartashevd570dfd2020-12-16 17:33:16 +030087 cpuInfo.clear();
Andrei Kartashev8e966032021-07-02 20:04:30 +030088 for (size_t addr = MIN_CLIENT_ADDR; addr <= MAX_CLIENT_ADDR; addr++)
Jason M. Billsd1e40602019-05-09 11:43:51 -070089 {
Andrei Kartashev8e966032021-07-02 20:04:30 +030090 if (peci_Ping(addr) != PECI_CC_SUCCESS)
Jason M. Billsd1e40602019-05-09 11:43:51 -070091 {
Andrei Kartashev8e966032021-07-02 20:04:30 +030092 continue;
Jason M. Bills5d049732019-10-25 15:55:15 -070093 }
Jason M. Bills5d049732019-10-25 15:55:15 -070094
Andrei Kartashev8e966032021-07-02 20:04:30 +030095 auto& cpu = cpuInfo.emplace_back(CPUInfo{addr, false, {}});
Jason M. Bills5d049732019-10-25 15:55:15 -070096 uint8_t cc = 0;
97 CPUModel model{};
98 uint8_t stepping = 0;
Andrei Kartashev8e966032021-07-02 20:04:30 +030099 if (peci_GetCPUID(addr, &model, &stepping, &cc) != PECI_CC_SUCCESS)
Jason M. Bills5d049732019-10-25 15:55:15 -0700100 {
101 std::cerr << "Cannot get CPUID!\n";
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300102 return resCode::resErr;
Jason M. Bills5d049732019-10-25 15:55:15 -0700103 }
104
105 switch (model)
106 {
107 case skx:
108 {
109 // Get the assigned CPU bus numbers from CPUBUSNO and CPUBUSNO1
110 // (B(0) D8 F2 offsets CCh and D0h)
111 uint32_t cpuBusNum = 0;
Andrei Kartashev8e966032021-07-02 20:04:30 +0300112 if (peci_RdPCIConfigLocal(addr, 0, 8, 2, 0xCC, 4,
Jason M. Bills5d049732019-10-25 15:55:15 -0700113 (uint8_t*)&cpuBusNum,
114 &cc) != PECI_CC_SUCCESS)
115 {
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300116 return resCode::resErr;
Jason M. Bills5d049732019-10-25 15:55:15 -0700117 }
118 uint32_t cpuBusNum1 = 0;
Andrei Kartashev8e966032021-07-02 20:04:30 +0300119 if (peci_RdPCIConfigLocal(addr, 0, 8, 2, 0xD0, 4,
Jason M. Bills5d049732019-10-25 15:55:15 -0700120 (uint8_t*)&cpuBusNum1,
121 &cc) != PECI_CC_SUCCESS)
122 {
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300123 return resCode::resErr;
Jason M. Bills5d049732019-10-25 15:55:15 -0700124 }
125
126 // Add the CPU bus numbers to the set for this CPU
127 while (cpuBusNum)
128 {
129 // Get the LSB
130 size_t busNum = cpuBusNum & 0xFF;
131 cpu.cpuBusNums.insert(busNum);
132 // Shift right by one byte
133 cpuBusNum >>= 8;
134 }
135 while (cpuBusNum1)
136 {
137 // Get the LSB
138 size_t busNum = cpuBusNum1 & 0xFF;
139 cpu.cpuBusNums.insert(busNum);
140 // Shift right by one byte
Zev Weiss9fa54b52020-09-02 21:20:33 +0000141 cpuBusNum1 >>= 8;
Jason M. Bills5d049732019-10-25 15:55:15 -0700142 }
143 cpu.skipCpuBuses = true;
144 }
Jason M. Billsd1e40602019-05-09 11:43:51 -0700145 }
146 }
Andrei Kartashev8e966032021-07-02 20:04:30 +0300147 return cpuInfo.empty() ? resCode::resErr : resCode::resOk;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700148}
149
150static bool isPECIAvailable(void)
151{
Jason M. Bills5d049732019-10-25 15:55:15 -0700152 for (size_t i = MIN_CLIENT_ADDR; i <= MAX_CLIENT_ADDR; i++)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700153 {
Jason M. Bills5d049732019-10-25 15:55:15 -0700154 if (peci_Ping(i) == PECI_CC_SUCCESS)
155 {
156 return true;
157 }
Jason M. Billsd1e40602019-05-09 11:43:51 -0700158 }
Jason M. Bills5d049732019-10-25 15:55:15 -0700159 return false;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700160}
161
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300162static resCode getDataFromPCIeConfig(const int& clientAddr, const int& bus,
163 const int& dev, const int& func,
164 const int& offset, const int& size,
165 uint32_t& pciData)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700166{
167 // PECI RdPCIConfig() currently only supports 4 byte reads, so adjust
168 // the offset and size to get the right data
169 static constexpr const int pciReadSize = 4;
170 int mod = offset % pciReadSize;
171 int pciOffset = offset - mod;
172 if (mod + size > pciReadSize)
173 {
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300174 return resCode::resErr;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700175 }
176
177 std::array<uint8_t, pciReadSize> data;
178 uint8_t cc;
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300179 int ret = PECI_CC_TIMEOUT;
180 for (int index = 0; (index < 5) && (ret == PECI_CC_TIMEOUT); index++)
181 {
Jason M. Bills3b1665a2021-06-11 13:35:04 -0700182#ifdef USE_RDENDPOINTCFG
183 ret = peci_RdEndPointConfigPci(clientAddr, // CPU Address
184 0, // PCI Seg (use 0 for now)
185 bus, // PCI Bus
186 dev, // PCI Device
187 func, // PCI Function
188 pciOffset, // PCI Offset
189 pciReadSize, // PCI Read Size
190 data.data(), // PCI Read Data
191 &cc); // PECI Completion Code
192#else
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300193 ret = peci_RdPCIConfig(clientAddr, // CPU Address
Jason M. Billsd1e40602019-05-09 11:43:51 -0700194 bus, // PCI Bus
195 dev, // PCI Device
196 func, // PCI Function
197 pciOffset, // PCI Offset
198 data.data(), // PCI Read Data
199 &cc); // PECI Completion Code
Jason M. Bills3b1665a2021-06-11 13:35:04 -0700200#endif
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300201 }
Jason M. Billsd1e40602019-05-09 11:43:51 -0700202 if (ret != PECI_CC_SUCCESS || cc != PECI_DEV_CC_SUCCESS)
203 {
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300204 return resCode::resErr;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700205 }
206
207 // Now build the requested data into a single number
208 pciData = 0;
209 for (int i = mod; i < mod + size; i++)
210 {
Jason M. Billse55832b2021-06-14 16:00:49 -0700211 pciData |= static_cast<uint32_t>(data[i]) << 8 * (i - mod);
Jason M. Billsd1e40602019-05-09 11:43:51 -0700212 }
213
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300214 return resCode::resOk;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700215}
216
Andrei Kartashev6f552032021-05-11 21:25:29 +0300217static resCode getStringFromData(const int& size, const uint32_t& data,
218 std::string& res)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700219{
Jason M. Billsd1e40602019-05-09 11:43:51 -0700220 // And convert it to a string
221 std::stringstream dataStream;
222 dataStream << "0x" << std::hex << std::setfill('0') << std::setw(size * 2)
223 << data;
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300224 res = dataStream.str();
225 return resCode::resOk;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700226}
227
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300228static resCode getVendorName(const int& clientAddr, const int& bus,
229 const int& dev, std::string& res)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700230{
231 static constexpr const int vendorIDOffset = 0x00;
232 static constexpr const int vendorIDSize = 2;
233
234 // Get the header type register from function 0
235 uint32_t vendorID = 0;
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300236 if (getDataFromPCIeConfig(clientAddr, bus, dev, 0, vendorIDOffset,
237 vendorIDSize, vendorID) != resCode::resOk)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700238 {
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300239 return resCode::resErr;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700240 }
241 // Get the vendor name or use Other if it doesn't exist
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300242 res = pciVendors.try_emplace(vendorID, otherVendor).first->second;
243 return resCode::resOk;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700244}
245
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300246static resCode getDeviceClass(const int& clientAddr, const int& bus,
247 const int& dev, const int& func, std::string& res)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700248{
249 static constexpr const int baseClassOffset = 0x0b;
250 static constexpr const int baseClassSize = 1;
251
252 // Get the Device Base Class
253 uint32_t baseClass = 0;
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300254 if (getDataFromPCIeConfig(clientAddr, bus, dev, func, baseClassOffset,
255 baseClassSize, baseClass) != resCode::resOk)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700256 {
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300257 return resCode::resErr;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700258 }
259 // Get the base class name or use Other if it doesn't exist
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300260 res = pciDeviceClasses.try_emplace(baseClass, otherClass).first->second;
261 return resCode::resOk;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700262}
263
Spencer Kubb5efe72021-09-02 16:11:14 +0800264static resCode getCapReading(const int& clientAddr, const int& bus,
265 const int& dev, uint32_t& capReading,
266 const int compareCapID, const int offsetAddress,
267 const int offsetLength)
268{
269 resCode error;
270 uint32_t capAddress = 0;
271 uint32_t capabilityID;
272 uint32_t nextCapPointer = peci_pcie::pointToCapStruct;
273
274 do
275 {
276 // Get capability address
277 error = getDataFromPCIeConfig(clientAddr, bus, dev, 0, nextCapPointer,
278 1, capAddress);
279 if (error != resCode::resOk)
280 {
281 return error;
282 }
283 // Capability struct address is a pointer which point to next capability
284 // struct, so if capability struct address is 0 means it doesn't have
285 // next capability struct.
286 if (capAddress == 0)
287 {
288 return resCode::resSkip;
289 }
290 // Get capability ID
291 error = getDataFromPCIeConfig(clientAddr, bus, dev, 0, capAddress, 1,
292 capabilityID);
293 if (error != resCode::resOk)
294 {
295 return error;
296 }
297 nextCapPointer = capAddress + peci_pcie::capPointerOffset;
298
299 } while (capabilityID != compareCapID);
300 // Get capability reading.
301 error = getDataFromPCIeConfig(clientAddr, bus, dev, 0,
302 capAddress + offsetAddress, offsetLength,
303 capReading);
304 if (error != resCode::resOk)
305 {
306 return error;
307 }
308 return resCode::resOk;
309}
310
311static resCode getGenerationInUse(const int& clientAddr, const int& bus,
312 const int& dev, std::string& generationInUse)
313{
Willy Tu975faf72022-09-23 18:39:16 +0000314 static std::unordered_set<uint32_t> linkSpeedSkipMap;
Spencer Kubb5efe72021-09-02 16:11:14 +0800315 resCode error;
316 std::string res;
317 uint32_t capReading = 0;
318
319 // Capability ID 0x10(16) is PCI Express
320 constexpr int pcieCapID = 16;
321 constexpr int capLength = 2;
322 uint32_t linkStatus;
323
324 error = getCapReading(clientAddr, bus, dev, linkStatus, pcieCapID,
325 peci_pcie::linkStatusOffset, capLength);
326 if (error != resCode::resOk)
327 {
328 return error;
329 }
330
331 uint32_t linkSpeed = linkStatus & peci_pcie::maskOfCLS;
332
333 switch (linkSpeed)
334 {
335 case peci_pcie::pcieGen1:
336 generationInUse = "xyz.openbmc_project.Inventory.Item."
337 "PCIeSlot.Generations.Gen1";
338 error = resCode::resOk;
339 break;
340 case peci_pcie::pcieGen2:
341 generationInUse = "xyz.openbmc_project.Inventory.Item."
342 "PCIeSlot.Generations.Gen2";
343 error = resCode::resOk;
344 break;
345 case peci_pcie::pcieGen3:
346 generationInUse = "xyz.openbmc_project.Inventory.Item."
347 "PCIeSlot.Generations.Gen3";
348 error = resCode::resOk;
349 break;
350 case peci_pcie::pcieGen4:
351 generationInUse = "xyz.openbmc_project.Inventory.Item."
352 "PCIeSlot.Generations.Gen4";
353 error = resCode::resOk;
354 break;
355 case peci_pcie::pcieGen5:
356 generationInUse = "xyz.openbmc_project.Inventory.Item."
357 "PCIeSlot.Generations.Gen5";
358 error = resCode::resOk;
359 break;
360 default:
Willy Tu975faf72022-09-23 18:39:16 +0000361 if (!linkSpeedSkipMap.contains(linkSpeed))
362 {
363 std::cerr << "Link speed : " << linkSpeed
364 << " can not mapping to PCIe type list.\n";
365 linkSpeedSkipMap.emplace(linkSpeed);
366 }
Spencer Kubb5efe72021-09-02 16:11:14 +0800367 error = resCode::resSkip;
368 }
369 return error;
370}
371
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300372static resCode isMultiFunction(const int& clientAddr, const int& bus,
373 const int& dev, bool& res)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700374{
375 static constexpr const int headerTypeOffset = 0x0e;
376 static constexpr const int headerTypeSize = 1;
377 static constexpr const int multiFuncBit = 1 << 7;
378
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300379 res = false;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700380 // Get the header type register from function 0
381 uint32_t headerType = 0;
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300382 if (getDataFromPCIeConfig(clientAddr, bus, dev, 0, headerTypeOffset,
383 headerTypeSize, headerType) != resCode::resOk)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700384 {
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300385 return resCode::resErr;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700386 }
387 // Check if it's a multifunction device
388 if (headerType & multiFuncBit)
389 {
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300390 res = true;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700391 }
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300392 return resCode::resOk;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700393}
394
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300395static resCode pcieFunctionExists(const int& clientAddr, const int& bus,
396 const int& dev, const int& func, bool& res)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700397{
398 constexpr const int pciIDOffset = 0;
399 constexpr const int pciIDSize = 4;
400 uint32_t pciID = 0;
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300401 res = false;
402 if (getDataFromPCIeConfig(clientAddr, bus, dev, func, pciIDOffset,
403 pciIDSize, pciID) != resCode::resOk)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700404 {
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300405 return resCode::resOk;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700406 }
407
408 // if VID and DID are all 0s or 1s, then the device doesn't exist
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300409 if (pciID != 0x00000000 && pciID != 0xFFFFFFFF)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700410 {
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300411 res = true;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700412 }
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300413 return resCode::resOk;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700414}
415
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300416static resCode pcieDeviceExists(const int& clientAddr, const int& bus,
417 const int& dev, bool& res)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700418{
419 // Check if this device exists by checking function 0
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300420 return pcieFunctionExists(clientAddr, bus, dev, 0, res);
Jason M. Billsd1e40602019-05-09 11:43:51 -0700421}
422
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300423static resCode setPCIeProperty(const int& clientAddr, const int& bus,
424 const int& dev, const std::string& propertyName,
425 const std::string& propertyValue)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700426{
427 std::shared_ptr<sdbusplus::asio::dbus_interface> iface =
428 peci_pcie::pcieDeviceDBusMap[clientAddr][bus][dev];
429
430 if (iface->is_initialized())
431 {
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300432 if (!iface->set_property(propertyName, propertyValue))
433 return resCode::resErr;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700434 }
435 else
436 {
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300437 if (!iface->register_property(propertyName, propertyValue))
438 return resCode::resErr;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700439 }
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300440 return resCode::resOk;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700441}
442
443static void setDefaultPCIeFunctionProperties(const int& clientAddr,
444 const int& bus, const int& dev,
445 const int& func)
446{
447 // Set the function-specific properties
Andrei Kartashev6f552032021-05-11 21:25:29 +0300448 for (const auto& [name, offset, size] : peci_pcie::pciConfigInfo)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700449 {
450 setPCIeProperty(clientAddr, bus, dev,
451 "Function" + std::to_string(func) + std::string(name),
452 std::string());
453 }
454}
455
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300456static resCode setPCIeFunctionProperties(const int& clientAddr, const int& bus,
457 const int& dev, const int& func)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700458{
Andrei Kartashev6f552032021-05-11 21:25:29 +0300459 uint32_t data = 0;
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300460 std::string res;
Andrei Kartashev6f552032021-05-11 21:25:29 +0300461 resCode error;
462
463 for (const auto& [name, offset, size] : peci_pcie::pciConfigInfo)
464 {
465 if (offset < 0)
466 {
467 continue;
468 }
469
470 error = getDataFromPCIeConfig(clientAddr, bus, dev, func, offset, size,
471 data);
472 if (error != resCode::resOk)
473 {
474 return error;
475 }
476 getStringFromData(size, data, res);
477 setPCIeProperty(clientAddr, bus, dev,
478 "Function" + std::to_string(func) + std::string(name),
479 res);
480 }
481
Jason M. Billsd1e40602019-05-09 11:43:51 -0700482 // Set the function type always to physical for now
483 setPCIeProperty(clientAddr, bus, dev,
484 "Function" + std::to_string(func) +
485 std::string(peci_pcie::function::functionTypeName),
486 "Physical");
487
488 // Set the function Device Class
Andrei Kartashev6f552032021-05-11 21:25:29 +0300489 error = getDeviceClass(clientAddr, bus, dev, func, res);
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300490 if (error != resCode::resOk)
491 {
492 return error;
493 }
Jason M. Billsd1e40602019-05-09 11:43:51 -0700494 setPCIeProperty(clientAddr, bus, dev,
495 "Function" + std::to_string(func) +
496 std::string(peci_pcie::function::deviceClassName),
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300497 res);
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300498 return resCode::resOk;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700499}
500
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300501static resCode setPCIeDeviceProperties(const int& clientAddr, const int& bus,
502 const int& dev)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700503{
504 // Set the device manufacturer
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300505 std::string manuf;
506 resCode error = getVendorName(clientAddr, bus, dev, manuf);
507 if (error != resCode::resOk)
508 {
509 return error;
510 }
511 setPCIeProperty(clientAddr, bus, dev, "Manufacturer", manuf);
Jason M. Billsd1e40602019-05-09 11:43:51 -0700512
513 // Set the device type
514 constexpr char const* deviceTypeName = "DeviceType";
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300515 bool multiFunc;
516 error = isMultiFunction(clientAddr, bus, dev, multiFunc);
517 if (error != resCode::resOk)
518 {
519 return error;
520 }
521 if (multiFunc)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700522 {
523 setPCIeProperty(clientAddr, bus, dev, deviceTypeName, "MultiFunction");
524 }
525 else
526 {
527 setPCIeProperty(clientAddr, bus, dev, deviceTypeName, "SingleFunction");
528 }
Spencer Kubb5efe72021-09-02 16:11:14 +0800529
530 // Set PCIe Generation
531 constexpr char const* generationInUseName = "GenerationInUse";
532 std::string generationInUse;
533 error = getGenerationInUse(clientAddr, bus, dev, generationInUse);
534 if (error == resCode::resErr)
535 {
536 return error;
537 }
538 // "resSkip" status means it can't get the capability reading, such like
539 // this device is not PCI Express.
540 if (error == resCode::resSkip)
541 {
542 setPCIeProperty(clientAddr, bus, dev, generationInUseName, "");
543 return resCode::resOk;
544 }
545 setPCIeProperty(clientAddr, bus, dev, generationInUseName, generationInUse);
546
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300547 return resCode::resOk;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700548}
549
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300550static resCode updatePCIeDevice(const int& clientAddr, const int& bus,
551 const int& dev)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700552{
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300553 if (setPCIeDeviceProperties(clientAddr, bus, dev) != resCode::resOk)
554 {
555 return resCode::resErr;
556 }
Jason M. Billsd1e40602019-05-09 11:43:51 -0700557
558 // Walk through and populate the functions for this device
559 for (int func = 0; func < peci_pcie::maxPCIFunctions; func++)
560 {
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300561 bool res;
562 resCode error = pcieFunctionExists(clientAddr, bus, dev, func, res);
563 if (error != resCode::resOk)
564 {
565 return error;
566 }
567 if (res)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700568 {
569 // Set the properties for this function
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300570 if (setPCIeFunctionProperties(clientAddr, bus, dev, func) !=
571 resCode::resOk)
572 {
573 return resCode::resErr;
574 }
Jason M. Billsd1e40602019-05-09 11:43:51 -0700575 }
576 else
577 {
578 // Set default properties for unused functions
579 setDefaultPCIeFunctionProperties(clientAddr, bus, dev, func);
580 }
581 }
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300582 return resCode::resOk;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700583}
584
585static void removePCIeDevice(sdbusplus::asio::object_server& objServer,
586 const int& clientAddr, const int& bus,
587 const int& dev)
588{
589 std::shared_ptr<sdbusplus::asio::dbus_interface> iface =
590 peci_pcie::pcieDeviceDBusMap[clientAddr][bus][dev];
591
592 objServer.remove_interface(iface);
593
594 peci_pcie::pcieDeviceDBusMap[clientAddr][bus].erase(dev);
595 if (peci_pcie::pcieDeviceDBusMap[clientAddr][bus].empty())
596 {
597 peci_pcie::pcieDeviceDBusMap[clientAddr].erase(bus);
598 }
599 if (peci_pcie::pcieDeviceDBusMap[clientAddr].empty())
600 {
601 peci_pcie::pcieDeviceDBusMap.erase(clientAddr);
602 }
603}
604
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300605static resCode addPCIeDevice(sdbusplus::asio::object_server& objServer,
606 const int& clientAddr, const int& cpu,
607 const int& bus, const int& dev)
608{
609 std::string pathName = std::string(peci_pcie::peciPCIePath) + "/S" +
610 std::to_string(cpu) + "B" + std::to_string(bus) +
611 "D" + std::to_string(dev);
612 std::shared_ptr<sdbusplus::asio::dbus_interface> iface =
613 objServer.add_interface(pathName, peci_pcie::peciPCIeDeviceInterface);
614 peci_pcie::pcieDeviceDBusMap[clientAddr][bus][dev] = iface;
615
616 // Update the properties for the new device
617 if (updatePCIeDevice(clientAddr, bus, dev) != resCode::resOk)
618 {
619 removePCIeDevice(objServer, clientAddr, bus, dev);
620 return resCode::resErr;
621 }
622
623 iface->initialize();
624 return resCode::resOk;
625}
626
Jason M. Billsd1e40602019-05-09 11:43:51 -0700627static bool pcieDeviceInDBusMap(const int& clientAddr, const int& bus,
628 const int& dev)
629{
630 if (auto clientAddrIt = peci_pcie::pcieDeviceDBusMap.find(clientAddr);
631 clientAddrIt != peci_pcie::pcieDeviceDBusMap.end())
632 {
633 if (auto busIt = clientAddrIt->second.find(bus);
634 busIt != clientAddrIt->second.end())
635 {
636 if (auto devIt = busIt->second.find(dev);
637 devIt != busIt->second.end())
638 {
639 if (devIt->second)
640 {
641 return true;
642 }
643 }
644 }
645 }
646 return false;
647}
648
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300649static resCode probePCIeDevice(boost::asio::io_service& io,
650 sdbusplus::asio::object_server& objServer,
Andrei Kartashev8e966032021-07-02 20:04:30 +0300651 size_t addr, int cpu, int bus, int dev)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700652{
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300653 bool res;
Andrei Kartashev8e966032021-07-02 20:04:30 +0300654 resCode error = pcieDeviceExists(addr, bus, dev, res);
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300655 if (error != resCode::resOk)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700656 {
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300657 return error;
Jason M. Bills5d049732019-10-25 15:55:15 -0700658 }
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300659 if (res)
Jason M. Bills5d049732019-10-25 15:55:15 -0700660 {
Andrei Kartashev8e966032021-07-02 20:04:30 +0300661 if (pcieDeviceInDBusMap(addr, bus, dev))
Jason M. Billsd1e40602019-05-09 11:43:51 -0700662 {
663 // This device is already in D-Bus, so update it
Andrei Kartashev8e966032021-07-02 20:04:30 +0300664 if (updatePCIeDevice(addr, bus, dev) != resCode::resOk)
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300665 {
666 return resCode::resErr;
667 }
Jason M. Billsd1e40602019-05-09 11:43:51 -0700668 }
669 else
670 {
671 // This device is not in D-Bus, so add it
Andrei Kartashev8e966032021-07-02 20:04:30 +0300672 if (addPCIeDevice(objServer, addr, cpu, bus, dev) != resCode::resOk)
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300673 {
674 return resCode::resErr;
675 }
Jason M. Billsd1e40602019-05-09 11:43:51 -0700676 }
677 }
678 else
679 {
680 // If PECI is not available, then stop scanning
681 if (!isPECIAvailable())
682 {
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300683 return resCode::resOk;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700684 }
685
Andrei Kartashev8e966032021-07-02 20:04:30 +0300686 if (pcieDeviceInDBusMap(addr, bus, dev))
Jason M. Billsd1e40602019-05-09 11:43:51 -0700687 {
688 // This device is in D-Bus, so remove it
Andrei Kartashev8e966032021-07-02 20:04:30 +0300689 removePCIeDevice(objServer, addr, bus, dev);
Jason M. Billsd1e40602019-05-09 11:43:51 -0700690 }
691 }
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300692 return resCode::resOk;
693}
694
Andrei Kartashev8e966032021-07-02 20:04:30 +0300695static void scanNextPCIeDevice(boost::asio::io_service& io,
696 sdbusplus::asio::object_server& objServer,
697 std::vector<CPUInfo>& cpuInfo, int cpu, int bus,
698 int dev);
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300699static void scanPCIeDevice(boost::asio::io_service& io,
700 sdbusplus::asio::object_server& objServer,
701 std::vector<CPUInfo>& cpuInfo, int cpu, int bus,
702 int dev)
703{
Andrei Kartashev8e966032021-07-02 20:04:30 +0300704 if (cpu >= cpuInfo.size())
705 {
706 std::cerr << "Request to scan CPU" << cpu
707 << " while CPU array has size " << cpuInfo.size() << "\n";
708 return;
709 }
710 auto& info = cpuInfo[cpu];
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300711 // Check if this is a CPU bus that we should skip
Andrei Kartashev8e966032021-07-02 20:04:30 +0300712 if (info.skipCpuBuses && info.cpuBusNums.count(bus))
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300713 {
714 std::cout << "Skipping CPU " << cpu << " Bus Number " << bus << "\n";
715 // Skip all the devices on this bus
716 dev = peci_pcie::maxPCIDevices;
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300717 }
Andrei Kartashev8e966032021-07-02 20:04:30 +0300718 else
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300719 {
Andrei Kartashev8e966032021-07-02 20:04:30 +0300720 if (probePCIeDevice(io, objServer, info.addr, cpu, bus, dev) !=
721 resCode::resOk)
722 {
723 std::cerr << "Failed to probe CPU " << cpu << " Bus " << bus
724 << " Device " << dev << "\n";
725 }
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300726 }
727
Jason M. Bills5d049732019-10-25 15:55:15 -0700728 scanNextPCIeDevice(io, objServer, cpuInfo, cpu, bus, dev);
Andrei Kartashev8e966032021-07-02 20:04:30 +0300729 return;
Jason M. Bills5d049732019-10-25 15:55:15 -0700730}
Jason M. Billsd1e40602019-05-09 11:43:51 -0700731
Jason M. Bills5d049732019-10-25 15:55:15 -0700732static void scanNextPCIeDevice(boost::asio::io_service& io,
733 sdbusplus::asio::object_server& objServer,
734 std::vector<CPUInfo>& cpuInfo, int cpu, int bus,
735 int dev)
736{
Jason M. Billsee6d80b2021-06-11 07:37:30 -0700737 if (peci_pcie::abortScan)
738 {
Paul Fertser07343142022-12-01 21:04:57 +0000739 peci_pcie::scanInProgress = false;
Jason M. Billsee6d80b2021-06-11 07:37:30 -0700740 std::cerr << "PCIe scan aborted\n";
741 return;
742 }
743
Jason M. Billsd1e40602019-05-09 11:43:51 -0700744 // PCIe Device scan completed, so move to the next device
745 if (++dev >= peci_pcie::maxPCIDevices)
746 {
747 // All devices scanned, so move to the next bus
748 dev = 0;
749 if (++bus >= peci_pcie::maxPCIBuses)
750 {
751 // All buses scanned, so move to the next CPU
752 bus = 0;
Jason M. Bills5d049732019-10-25 15:55:15 -0700753 if (++cpu >= cpuInfo.size())
Jason M. Billsd1e40602019-05-09 11:43:51 -0700754 {
755 // All CPUs scanned, so we're done
Paul Fertser07343142022-12-01 21:04:57 +0000756 peci_pcie::scanInProgress = false;
Jason M. Billsee6d80b2021-06-11 07:37:30 -0700757 std::cerr << "PCIe scan completed\n";
Jason M. Billsd1e40602019-05-09 11:43:51 -0700758 return;
759 }
760 }
761 }
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300762 boost::asio::post(io, [&io, &objServer, &cpuInfo, cpu, bus, dev]() mutable {
Jason M. Bills5d049732019-10-25 15:55:15 -0700763 scanPCIeDevice(io, objServer, cpuInfo, cpu, bus, dev);
Jason M. Billsd1e40602019-05-09 11:43:51 -0700764 });
765}
766
Paul Fertser07343142022-12-01 21:04:57 +0000767static void startPCIeScan(boost::asio::io_service& io,
768 sdbusplus::asio::object_server& objServer,
769 std::vector<CPUInfo>& cpuInfo)
770{
771 if (!peci_pcie::scanInProgress)
772 {
773 // get the PECI client address list
774 if (getCPUBusMap(cpuInfo) != resCode::resOk)
775 {
776 return;
777 }
778 std::cerr << "PCIe scan started\n";
779 // scan PCIe starting from CPU 0, Bus 0, Device 0
780 peci_pcie::scanInProgress = true;
781 scanPCIeDevice(io, objServer, cpuInfo, 0, 0, 0);
782 }
783}
784
Jason M. Billsd1e40602019-05-09 11:43:51 -0700785static void peciAvailableCheck(boost::asio::steady_timer& peciWaitTimer,
786 boost::asio::io_service& io,
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300787 sdbusplus::asio::object_server& objServer,
788 std::vector<CPUInfo>& cpuInfo)
Jason M. Billsd1e40602019-05-09 11:43:51 -0700789{
Jason M. Bills5d049732019-10-25 15:55:15 -0700790 static bool lastPECIState = false;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700791 bool peciAvailable = isPECIAvailable();
792 if (peciAvailable && !lastPECIState)
793 {
794 lastPECIState = true;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700795 static boost::asio::steady_timer pcieTimeout(io);
796 constexpr const int pcieWaitTime = 60;
797 pcieTimeout.expires_after(std::chrono::seconds(pcieWaitTime));
798 pcieTimeout.async_wait(
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300799 [&io, &objServer, &cpuInfo](const boost::system::error_code& ec) {
Jason M. Billsd1e40602019-05-09 11:43:51 -0700800 if (ec)
801 {
802 // operation_aborted is expected if timer is canceled
803 // before completion.
804 if (ec != boost::asio::error::operation_aborted)
805 {
806 std::cerr << "PECI PCIe async_wait failed " << ec;
807 }
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300808 lastPECIState = false;
Jason M. Billsd1e40602019-05-09 11:43:51 -0700809 return;
810 }
Paul Fertser07343142022-12-01 21:04:57 +0000811 startPCIeScan(io, objServer, cpuInfo);
Jason M. Billsd1e40602019-05-09 11:43:51 -0700812 });
813 }
814 else if (!peciAvailable && lastPECIState)
815 {
816 lastPECIState = false;
817 }
818
819 peciWaitTimer.expires_after(
820 std::chrono::seconds(peci_pcie::peciCheckInterval));
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300821 peciWaitTimer.async_wait([&peciWaitTimer, &io, &objServer,
822 &cpuInfo](const boost::system::error_code& ec) {
Jason M. Billsd1e40602019-05-09 11:43:51 -0700823 if (ec)
824 {
825 // operation_aborted is expected if timer is canceled
826 // before completion.
827 if (ec != boost::asio::error::operation_aborted)
828 {
829 std::cerr << "PECI Available Check async_wait failed " << ec;
830 }
831 return;
832 }
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300833 peciAvailableCheck(peciWaitTimer, io, objServer, cpuInfo);
Jason M. Billsd1e40602019-05-09 11:43:51 -0700834 });
835}
836
Jason M. Billsee6d80b2021-06-11 07:37:30 -0700837static void waitForOSStandbyDelay(boost::asio::io_service& io,
838 sdbusplus::asio::object_server& objServer,
839 boost::asio::steady_timer& osStandbyTimer,
840 std::vector<CPUInfo>& cpuInfo)
841{
842 osStandbyTimer.expires_after(
843 std::chrono::seconds(peci_pcie::osStandbyDelaySeconds));
844
845 osStandbyTimer.async_wait(
846 [&io, &objServer, &cpuInfo](const boost::system::error_code& ec) {
847 if (ec == boost::asio::error::operation_aborted)
848 {
849 return; // we're being canceled
850 }
851 else if (ec)
852 {
853 std::cerr << "OS Standby async_wait failed: " << ec.value()
854 << ": " << ec.message() << "\n";
855 return;
856 }
Paul Fertser07343142022-12-01 21:04:57 +0000857 startPCIeScan(io, objServer, cpuInfo);
Jason M. Billsee6d80b2021-06-11 07:37:30 -0700858 });
859}
860
861static void monitorOSStandby(boost::asio::io_service& io,
862 std::shared_ptr<sdbusplus::asio::connection> conn,
863 sdbusplus::asio::object_server& objServer,
864 boost::asio::steady_timer& osStandbyTimer,
865 std::vector<CPUInfo>& cpuInfo)
866{
867 std::cerr << "Start OperatingSystemState Monitor\n";
868
Patrick Williamsb2517082022-07-22 19:26:57 -0500869 static sdbusplus::bus::match_t osStateMatch(
Jason M. Billsee6d80b2021-06-11 07:37:30 -0700870 *conn,
871 "type='signal',interface='org.freedesktop.DBus.Properties',member='"
872 "PropertiesChanged',arg0='xyz.openbmc_project.State.OperatingSystem."
873 "Status'",
874 [&io, &objServer, &osStandbyTimer,
Patrick Williamsb2517082022-07-22 19:26:57 -0500875 &cpuInfo](sdbusplus::message_t& msg) {
Jason M. Billsee6d80b2021-06-11 07:37:30 -0700876 // Get the OS State from the message
877 std::string osStateInterface;
878 boost::container::flat_map<std::string, std::variant<std::string>>
879 propertiesChanged;
880 msg.read(osStateInterface, propertiesChanged);
881
882 for (const auto& [name, value] : propertiesChanged)
883 {
884 if (name == "OperatingSystemState")
885 {
886 const std::string* state = std::get_if<std::string>(&value);
887 if (state == nullptr)
888 {
889 std::cerr << "Unable to read OS state value\n";
890 return;
891 }
Andrei Kartashev328685e2021-12-27 17:24:18 +0300892 // Note: Short version of OperatingSystemState value is
893 // deprecated and would be removed in the future
894 if ((*state == "Standby") ||
895 (*state == "xyz.openbmc_project.State.OperatingSystem."
896 "Status.OSStatus.Standby"))
Jason M. Billsee6d80b2021-06-11 07:37:30 -0700897 {
898 peci_pcie::abortScan = false;
899 waitForOSStandbyDelay(io, objServer, osStandbyTimer,
900 cpuInfo);
901 }
Andrei Kartashev328685e2021-12-27 17:24:18 +0300902 else if ((*state == "Inactive") ||
903 (*state ==
904 "xyz.openbmc_project.State.OperatingSystem."
905 "Status.OSStatus.Inactive"))
Jason M. Billsee6d80b2021-06-11 07:37:30 -0700906 {
907 peci_pcie::abortScan = true;
908 osStandbyTimer.cancel();
909 }
910 }
911 }
912 });
913
914 // Check if the OS state is already available
915 conn->async_method_call(
916 [&io, &objServer, &osStandbyTimer,
917 &cpuInfo](boost::system::error_code ec,
918 const std::variant<std::string>& property) {
919 if (ec)
920 {
921 std::cerr << "error with OS state async_method_call\n";
922 return;
923 }
924
925 const std::string* state = std::get_if<std::string>(&property);
926 if (state == nullptr)
927 {
928 std::cerr << "Unable to read OS state value\n";
929 return;
930 }
931
932 // If the OS state is in Standby, then BIOS is done and we can
933 // continue. Otherwise, we just wait for the match
Andrei Kartashev328685e2021-12-27 17:24:18 +0300934 // Note: Short version of OperatingSystemState value is deprecated
935 // and would be removed in the future
936
937 if ((*state == "Standby") ||
938 (*state == "xyz.openbmc_project.State.OperatingSystem.Status."
939 "OSStatus.Standby"))
Jason M. Billsee6d80b2021-06-11 07:37:30 -0700940 {
941 waitForOSStandbyDelay(io, objServer, osStandbyTimer, cpuInfo);
942 }
943 },
944 "xyz.openbmc_project.State.OperatingSystem",
945 "/xyz/openbmc_project/state/os", "org.freedesktop.DBus.Properties",
946 "Get", "xyz.openbmc_project.State.OperatingSystem.Status",
947 "OperatingSystemState");
948}
949
Jason M. Billsd1e40602019-05-09 11:43:51 -0700950int main(int argc, char* argv[])
951{
952 // setup connection to dbus
953 boost::asio::io_service io;
954 std::shared_ptr<sdbusplus::asio::connection> conn =
955 std::make_shared<sdbusplus::asio::connection>(io);
956
957 // PECI PCIe Object
958 conn->request_name(peci_pcie::peciPCIeObject);
959 sdbusplus::asio::object_server server =
960 sdbusplus::asio::object_server(conn);
961
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300962 // CPU map
963 std::vector<CPUInfo> cpuInfo;
964
Jason M. Billsee6d80b2021-06-11 07:37:30 -0700965#ifdef WAIT_FOR_OS_STANDBY
966 boost::asio::steady_timer osStandbyTimer(io);
967 monitorOSStandby(io, conn, server, osStandbyTimer, cpuInfo);
968#else
Jason M. Billsd1e40602019-05-09 11:43:51 -0700969 // Start the PECI check loop
970 boost::asio::steady_timer peciWaitTimer(
971 io, std::chrono::seconds(peci_pcie::peciCheckInterval));
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300972 peciWaitTimer.async_wait([&peciWaitTimer, &io, &server,
973 &cpuInfo](const boost::system::error_code& ec) {
Jason M. Billsd1e40602019-05-09 11:43:51 -0700974 if (ec)
975 {
976 // operation_aborted is expected if timer is canceled
977 // before completion.
978 if (ec != boost::asio::error::operation_aborted)
979 {
980 std::cerr << "PECI Available Check async_wait failed " << ec;
981 }
982 return;
983 }
Andrei Kartashevd570dfd2020-12-16 17:33:16 +0300984 peciAvailableCheck(peciWaitTimer, io, server, cpuInfo);
Jason M. Billsd1e40602019-05-09 11:43:51 -0700985 });
Jason M. Billsee6d80b2021-06-11 07:37:30 -0700986#endif
Jason M. Billsd1e40602019-05-09 11:43:51 -0700987
988 io.run();
989
990 return 0;
991}