oem-ampere: eventManager: Support polling the RAS CEs

The events for RAS CEs is disabled by default. The Poll-based mechanizm
is required to check the existing of RAS CEs errors.
Add Ampere Poll-based mechanizm to poll RAS CEs events.

Change-Id: Iad48ef28a5dbd1dfe53506c0ac9f3a3e1eec2e22
Signed-off-by: Dung Cao <dung@os.amperecomputing.com>
Signed-off-by: Thu Nguyen <thu@os.amperecomputing.com>
diff --git a/oem/ampere/event/oem_event_manager.cpp b/oem/ampere/event/oem_event_manager.cpp
index dcd3fa9..7a2acff 100644
--- a/oem/ampere/event/oem_event_manager.cpp
+++ b/oem/ampere/event/oem_event_manager.cpp
@@ -25,6 +25,9 @@
 {
 namespace oem_ampere
 {
+namespace fs = std::filesystem;
+using namespace std::chrono;
+
 namespace boot_stage = boot::stage;
 namespace ddr_status = ddr::status;
 namespace dimm_status = dimm::status;
@@ -992,5 +995,33 @@
     return PLDM_SUCCESS;
 }
 
+exec::task<int> OemEventManager::oemPollForPlatformEvent(pldm_tid_t tid)
+{
+    uint64_t t0 = 0;
+
+    /* This OEM event handler is only used for SoC terminus */
+    if (!tidToSocketNameMap.contains(tid))
+    {
+        co_return PLDM_SUCCESS;
+    }
+
+    if (!timeStampMap.contains(tid))
+    {
+        sd_event_now(event.get(), CLOCK_MONOTONIC, &t0);
+        timeStampMap.emplace(std::make_pair(tid, t0));
+    }
+    else
+    {
+        sd_event_now(event.get(), CLOCK_MONOTONIC, &t0);
+        uint64_t elapsed = t0 - timeStampMap[tid];
+        if (elapsed >= NORMAL_EVENT_POLLING_TIME)
+        {
+            co_await manager->pollForPlatformEvent(tid, 0, 0);
+            timeStampMap[tid] = t0;
+        }
+    }
+
+    co_return PLDM_SUCCESS;
+}
 } // namespace oem_ampere
 } // namespace pldm
diff --git a/oem/ampere/event/oem_event_manager.hpp b/oem/ampere/event/oem_event_manager.hpp
index acade3f..2f76909 100644
--- a/oem/ampere/event/oem_event_manager.hpp
+++ b/oem/ampere/event/oem_event_manager.hpp
@@ -14,6 +14,7 @@
 namespace oem_ampere
 {
 using namespace pldm::pdr;
+#define NORMAL_EVENT_POLLING_TIME 5000000 // ms
 
 using EventToMsgMap_t = std::unordered_map<uint8_t, std::string>;
 
@@ -242,7 +243,9 @@
     explicit OemEventManager(
         sdeventplus::Event& event,
         requester::Handler<requester::Request>* /* handler */,
-        pldm::InstanceIdDb& /* instanceIdDb */) : event(event) {};
+        pldm::InstanceIdDb& /* instanceIdDb */,
+        platform_mc::Manager* platformManager) :
+        event(event), manager(platformManager) {};
 
     /** @brief Decode sensor event messages and handle correspondingly.
      *
@@ -284,6 +287,13 @@
         const pldm_msg* request, size_t payloadLength,
         uint8_t /* formatVersion */, pldm_tid_t tid, size_t eventDataOffset);
 
+    /** @brief A Coroutine to do OEM PollForPlatformEvent action
+     *
+     *  @param[in] tid - the destination TID
+     *  @return coroutine return_value - PLDM completion code
+     */
+    exec::task<int> oemPollForPlatformEvent(pldm_tid_t tid);
+
   protected:
     /** @brief Create prefix string for logging message.
      *
@@ -425,6 +435,12 @@
      *  work
      */
     sdeventplus::Event& event;
+
+    /** @brief Latest OEM PollForPlatformEvent message timeStamp. */
+    std::map<pldm_tid_t, uint64_t> timeStampMap;
+
+    /** @brief A Manager interface for calling the hook functions */
+    platform_mc::Manager* manager;
 };
 } // namespace oem_ampere
 } // namespace pldm
diff --git a/oem/ampere/oem_ampere.hpp b/oem/ampere/oem_ampere.hpp
index 8e8c301..e2c298d 100644
--- a/oem/ampere/oem_ampere.hpp
+++ b/oem/ampere/oem_ampere.hpp
@@ -62,7 +62,8 @@
         reqHandler(reqHandler)
     {
         oemEventManager = std::make_shared<oem_ampere::OemEventManager>(
-            this->event, this->reqHandler, this->instanceIdDb);
+            this->event, this->reqHandler, this->instanceIdDb,
+            this->platformManager);
         createOemEventHandler(oemEventManager.get(), this->platformManager);
     }
 
@@ -133,6 +134,12 @@
                     request, payloadLength, formatVersion, tid,
                     eventDataOffset);
             }});
+
+        /* Register Ampere OEM handler to poll the PLDM events */
+        platformManager->registerOEMPollMethod(
+            [oemEventManager](pldm_tid_t tid) {
+                return oemEventManager->oemPollForPlatformEvent(tid);
+            });
     }
 
   private: