Abort the scan on errors

If PECI becomes unavailable there is no reason to continue scanning as
we might miss information about the devices that are really present,
better to start it from the beginning when PECI communication is back to
normal.

Tested: powering off the host while the scan is ongoing makes it stop,
powering on the host later restarts the process from the beginning; same
about host restarts performed from the UEFI menu and OS.

Signed-off-by: Paul Fertser <fercerpav@gmail.com>
Change-Id: Ib61e84d1bc271a77343d0e380293c852670ca572
diff --git a/src/peci_pcie.cpp b/src/peci_pcie.cpp
index 312e339..e65f33f 100644
--- a/src/peci_pcie.cpp
+++ b/src/peci_pcie.cpp
@@ -199,10 +199,14 @@
                                &cc);        // PECI Completion Code
 #endif
     }
-    if (ret != PECI_CC_SUCCESS || cc != PECI_DEV_CC_SUCCESS)
+    if (ret != PECI_CC_SUCCESS)
     {
         return resCode::resErr;
     }
+    else if (cc != PECI_DEV_CC_SUCCESS)
+    {
+        return resCode::resSkip;
+    }
 
     // Now build the requested data into a single number
     pciData = 0;
@@ -399,11 +403,17 @@
     constexpr const int pciIDSize = 4;
     uint32_t pciID = 0;
     res = false;
-    if (getDataFromPCIeConfig(clientAddr, bus, dev, func, pciIDOffset,
-                              pciIDSize, pciID) != resCode::resOk)
+
+    resCode error = getDataFromPCIeConfig(clientAddr, bus, dev, func,
+                                          pciIDOffset, pciIDSize, pciID);
+    if (error == resCode::resSkip)
     {
         return resCode::resOk;
     }
+    else if (error == resCode::resErr)
+    {
+        return resCode::resErr;
+    }
 
     // if VID and DID are all 0s or 1s, then the device doesn't exist
     if (pciID != 0x00000000 && pciID != 0xFFFFFFFF)
@@ -680,7 +690,7 @@
         // If PECI is not available, then stop scanning
         if (!isPECIAvailable())
         {
-            return resCode::resOk;
+            return resCode::resErr;
         }
 
         if (pcieDeviceInDBusMap(addr, bus, dev))
@@ -722,6 +732,7 @@
         {
             std::cerr << "Failed to probe CPU " << cpu << " Bus " << bus
                       << " Device " << dev << "\n";
+            peci_pcie::abortScan = true;
         }
     }
 
@@ -773,11 +784,13 @@
         // get the PECI client address list
         if (getCPUBusMap(cpuInfo) != resCode::resOk)
         {
+            peci_pcie::abortScan = true;
             return;
         }
         std::cerr << "PCIe scan started\n";
         // scan PCIe starting from CPU 0, Bus 0, Device 0
         peci_pcie::scanInProgress = true;
+        peci_pcie::abortScan = false;
         scanPCIeDevice(io, objServer, cpuInfo, 0, 0, 0);
     }
 }
@@ -789,27 +802,27 @@
 {
     static bool lastPECIState = false;
     bool peciAvailable = isPECIAvailable();
-    if (peciAvailable && !lastPECIState)
+    if (peciAvailable && (!lastPECIState || peci_pcie::abortScan))
     {
         lastPECIState = true;
-        static boost::asio::steady_timer pcieTimeout(io);
+        auto pcieTimeout = std::make_shared<boost::asio::steady_timer>(io);
         constexpr const int pcieWaitTime = 60;
-        pcieTimeout.expires_after(std::chrono::seconds(pcieWaitTime));
-        pcieTimeout.async_wait(
-            [&io, &objServer, &cpuInfo](const boost::system::error_code& ec) {
-                if (ec)
+        pcieTimeout->expires_after(std::chrono::seconds(pcieWaitTime));
+        pcieTimeout->async_wait([&io, &objServer, &cpuInfo, pcieTimeout](
+                                    const boost::system::error_code& ec) {
+            if (ec)
+            {
+                // operation_aborted is expected if timer is canceled
+                // before completion.
+                if (ec != boost::asio::error::operation_aborted)
                 {
-                    // operation_aborted is expected if timer is canceled
-                    // before completion.
-                    if (ec != boost::asio::error::operation_aborted)
-                    {
-                        std::cerr << "PECI PCIe async_wait failed " << ec;
-                    }
-                    lastPECIState = false;
-                    return;
+                    std::cerr << "PECI PCIe async_wait failed " << ec;
                 }
-                startPCIeScan(io, objServer, cpuInfo);
-            });
+                lastPECIState = false;
+                return;
+            }
+            startPCIeScan(io, objServer, cpuInfo);
+        });
     }
     else if (!peciAvailable && lastPECIState)
     {