PEL: Notifier support for 'host full'

The host firmware may have a limited size for its staging area
before it passes the PELs through to the OS, and this area may
fill up with PELs it can't send if there are too many or the OS
isn't up yet.

In this case, it will send down an 'Ack PEL' PLDM command with a
special response indicating this host full condition.  The PLDM
daemon will then call a method on this daemon to let it know.

This command handles the host full condition on the HostNotifier
class.  When this is set:

* The PEL that hit this condition will be put back on the queue
  to be sent again.
* No new PELs will be sent up, except as noted below
* A 60s timer will be started at the end of which another attempt
  will be made to send a PEL, in the hopes the condition went away.
  - If it didn't go away, this process will repeat.
  - If it did go away, a successful ack will be received and things
    will proceed as normal.

Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: Iaeb38f43f7acc595bcff234ba50cedf8188b3d9b
diff --git a/extensions/openpower-pels/host_notifier.hpp b/extensions/openpower-pels/host_notifier.hpp
index d160dd4..21bd072 100644
--- a/extensions/openpower-pels/host_notifier.hpp
+++ b/extensions/openpower-pels/host_notifier.hpp
@@ -87,10 +87,36 @@
      *
      * This means the PEL never needs to be sent up again.
      *
+     * If the host was previously full, it is also an indication
+     * it no longer is.
+     *
      * @param[in] id - The PEL ID
      */
     void ackPEL(uint32_t id);
 
+    /**
+     * @brief Called when the host does not have room for more
+     *        PELs at this time.
+     *
+     * This can happen when an OS isn't running yet, and the
+     * staging area to hold the PELs before sending them up
+     * to the OS is full.  This will stop future PEls from being
+     * sent up, as explained below.
+     *
+     * The PEL with this ID will need to be sent again, so its
+     * state is set back to 'new', and it is removed from the list
+     * of already sent PELs.
+     *
+     * A timer will be started, if it isn't already running, to
+     * issue another send in the hopes that space has been freed
+     * up by then (Receiving an ackPEL response is also an
+     * indication of this if there happened to have been other
+     * PELs in flight).
+     *
+     * @param[in] id - The PEL ID
+     */
+    void setHostFull(uint32_t id);
+
   private:
     /**
      * @brief This function gets called by the Repository class
@@ -171,6 +197,15 @@
     void retryTimerExpired();
 
     /**
+     * @brief The function called when the 'host full' retry timer
+     *        expires.
+     *
+     * This will re-issue a command to try again with the PEL at
+     * the front of the queue.
+     */
+    void hostFullTimerExpired();
+
+    /**
      * @brief Stops an in progress command
      *
      * In progress meaning after the send but before the response.
@@ -217,11 +252,23 @@
     size_t _retryCount = 0;
 
     /**
+     * @brief Indicates if the host has said it is full and does not
+     *        currently have the space for more PELs.
+     */
+    bool _hostFull = false;
+
+    /**
      * @brief The command retry timer.
      */
     sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> _retryTimer;
 
     /**
+     * @brief The host full timer, used to retry sending a PEL if the host
+     *        said it is full.
+     */
+    sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> _hostFullTimer;
+
+    /**
      * @brief The object used to dispatch a new PEL send from the
      *        event loop, so the calling function can be returned from
      *        first.