1f60ac27eSMatt Spinler #pragma once
2f60ac27eSMatt Spinler 
3f60ac27eSMatt Spinler #include "host_interface.hpp"
4f60ac27eSMatt Spinler #include "pel.hpp"
5f60ac27eSMatt Spinler #include "repository.hpp"
6f60ac27eSMatt Spinler 
7f60ac27eSMatt Spinler #include <deque>
8f869fcf8SMatt Spinler #include <sdeventplus/clock.hpp>
9f869fcf8SMatt Spinler #include <sdeventplus/utility/timer.hpp>
10f60ac27eSMatt Spinler 
11f60ac27eSMatt Spinler namespace openpower::pels
12f60ac27eSMatt Spinler {
13f60ac27eSMatt Spinler 
14f60ac27eSMatt Spinler /**
15f60ac27eSMatt Spinler  * @class HostNotifier
16f60ac27eSMatt Spinler  *
17f60ac27eSMatt Spinler  * This class handles notifying the host firmware of new PELs.
18f60ac27eSMatt Spinler  */
19f60ac27eSMatt Spinler class HostNotifier
20f60ac27eSMatt Spinler {
21f60ac27eSMatt Spinler   public:
22f60ac27eSMatt Spinler     HostNotifier() = delete;
23f60ac27eSMatt Spinler     HostNotifier(const HostNotifier&) = delete;
24f60ac27eSMatt Spinler     HostNotifier& operator=(const HostNotifier&) = delete;
25f60ac27eSMatt Spinler     HostNotifier(HostNotifier&&) = delete;
26f60ac27eSMatt Spinler     HostNotifier& operator=(HostNotifier&&) = delete;
27f60ac27eSMatt Spinler 
28f60ac27eSMatt Spinler     /**
29f60ac27eSMatt Spinler      * @brief Constructor
30f60ac27eSMatt Spinler      *
31f60ac27eSMatt Spinler      * @param[in] repo - The PEL repository object
32f60ac27eSMatt Spinler      * @param[in] dataIface - The data interface object
33f60ac27eSMatt Spinler      * @param[in] hostIface - The host interface object
34f60ac27eSMatt Spinler      */
35f60ac27eSMatt Spinler     HostNotifier(Repository& repo, DataInterfaceBase& dataIface,
36f60ac27eSMatt Spinler                  std::unique_ptr<HostInterface> hostIface);
37f60ac27eSMatt Spinler 
38f60ac27eSMatt Spinler     /**
39f60ac27eSMatt Spinler      * @brief Destructor
40f60ac27eSMatt Spinler      */
41f60ac27eSMatt Spinler     ~HostNotifier();
42f60ac27eSMatt Spinler 
43f60ac27eSMatt Spinler     /**
44f60ac27eSMatt Spinler      * @brief Returns the PEL queue size.
45f60ac27eSMatt Spinler      *
46f60ac27eSMatt Spinler      * For testing.
47f60ac27eSMatt Spinler      *
48f60ac27eSMatt Spinler      * @return size_t - The queue size
49f60ac27eSMatt Spinler      */
50f60ac27eSMatt Spinler     size_t queueSize() const
51f60ac27eSMatt Spinler     {
52f60ac27eSMatt Spinler         return _pelQueue.size();
53f60ac27eSMatt Spinler     }
54f60ac27eSMatt Spinler 
55f60ac27eSMatt Spinler     /**
56f60ac27eSMatt Spinler      * @brief Specifies if the PEL needs to go onto the queue to be
57f60ac27eSMatt Spinler      *        set to the host.
58f60ac27eSMatt Spinler      *
59a943b15bSMatt Spinler      * Only returns false if:
60a943b15bSMatt Spinler      *  - Already acked by the host (or they didn't like it)
61a943b15bSMatt Spinler      *  - Hidden and the HMC already got it
62a943b15bSMatt Spinler      *  - The 'do not report to host' bit is set
63a943b15bSMatt Spinler      *
64f60ac27eSMatt Spinler      * @param[in] id - The PEL ID
65f60ac27eSMatt Spinler      *
66f60ac27eSMatt Spinler      * @return bool - If enqueue is required
67f60ac27eSMatt Spinler      */
68f60ac27eSMatt Spinler     bool enqueueRequired(uint32_t id) const;
69f60ac27eSMatt Spinler 
70*f77debb9SMatt Spinler     /**
71*f77debb9SMatt Spinler      * @brief If the host still needs to be notified of the PEL
72*f77debb9SMatt Spinler      *        at the time of the notification.
73*f77debb9SMatt Spinler      *
74*f77debb9SMatt Spinler      * Only returns false if:
75*f77debb9SMatt Spinler      *  - Already acked by the host
76*f77debb9SMatt Spinler      *  - It's hidden, and the HMC already got or will get it.
77*f77debb9SMatt Spinler      *
78*f77debb9SMatt Spinler      * @param[in] id - The PEL ID
79*f77debb9SMatt Spinler      *
80*f77debb9SMatt Spinler      * @return bool - If the notify is required
81*f77debb9SMatt Spinler      */
82*f77debb9SMatt Spinler     bool notifyRequired(uint32_t id) const;
83*f77debb9SMatt Spinler 
84f60ac27eSMatt Spinler   private:
85f60ac27eSMatt Spinler     /**
86f60ac27eSMatt Spinler      * @brief This function gets called by the Repository class
87f60ac27eSMatt Spinler      *        when a new PEL is added to it.
88f60ac27eSMatt Spinler      *
89f60ac27eSMatt Spinler      * @param[in] pel - The new PEL
90f60ac27eSMatt Spinler      */
91f60ac27eSMatt Spinler     void newLogCallback(const PEL& pel);
92f60ac27eSMatt Spinler 
93f60ac27eSMatt Spinler     /**
94f60ac27eSMatt Spinler      * @brief This function runs on every existing PEL at startup
95f60ac27eSMatt Spinler      *        and puts the PEL on the queue to send if necessary.
96f60ac27eSMatt Spinler      *
97f60ac27eSMatt Spinler      * @param[in] pel - The PEL
98f60ac27eSMatt Spinler      *
99f60ac27eSMatt Spinler      * @return bool - This is an indicator to the Repository::for_each
100f60ac27eSMatt Spinler      *                function to traverse every PEL.  Always false.
101f60ac27eSMatt Spinler      */
102f60ac27eSMatt Spinler     bool addPELToQueue(const PEL& pel);
103f60ac27eSMatt Spinler 
104f60ac27eSMatt Spinler     /**
105*f77debb9SMatt Spinler      * @brief Takes the first PEL from the queue that needs to be
106*f77debb9SMatt Spinler      *        sent, and issues the send if conditions are right.
107f60ac27eSMatt Spinler      */
108f60ac27eSMatt Spinler     void doNewLogNotify();
109f60ac27eSMatt Spinler 
110f60ac27eSMatt Spinler     /**
111f60ac27eSMatt Spinler      * @brief Called when the host changes state.
112f60ac27eSMatt Spinler      *
1133019c6fbSMatt Spinler      * If the new state is host up and there are PELs to send, it
1143019c6fbSMatt Spinler      * will trigger the first command.  If the new state is off, then
1153019c6fbSMatt Spinler      * it will transfer any PELs that were sent but not acked yet back
1163019c6fbSMatt Spinler      * to the queue to be sent again.
1173019c6fbSMatt Spinler      *
118f60ac27eSMatt Spinler      * @param[in] hostUp - The new host state
119f60ac27eSMatt Spinler      */
120f60ac27eSMatt Spinler     void hostStateChange(bool hostUp);
121f60ac27eSMatt Spinler 
122f60ac27eSMatt Spinler     /**
123f60ac27eSMatt Spinler      * @brief The callback function invoked after the asynchronous
124f60ac27eSMatt Spinler      *        PLDM receive function is complete.
125f60ac27eSMatt Spinler      *
126f869fcf8SMatt Spinler      * If the command was successful, the state of that PEL will
127f869fcf8SMatt Spinler      * be set to 'sent', and the next send will be triggered.
128f869fcf8SMatt Spinler      *
129f869fcf8SMatt Spinler      * If the command failed, a retry timer will be started so it
130f869fcf8SMatt Spinler      * can be sent again.
131f869fcf8SMatt Spinler      *
132f60ac27eSMatt Spinler      * @param[in] status - The response status
133f60ac27eSMatt Spinler      */
134f60ac27eSMatt Spinler     void commandResponse(ResponseStatus status);
135f60ac27eSMatt Spinler 
136f60ac27eSMatt Spinler     /**
137f869fcf8SMatt Spinler      * @brief The function called when the command failure retry
138f869fcf8SMatt Spinler      *        time is up.
139f869fcf8SMatt Spinler      *
140f869fcf8SMatt Spinler      * It will issue a send of the previous PEL and increment the
141f869fcf8SMatt Spinler      * retry count.
142f869fcf8SMatt Spinler      */
143f869fcf8SMatt Spinler     void retryTimerExpired();
144f869fcf8SMatt Spinler 
145f869fcf8SMatt Spinler     /**
1463019c6fbSMatt Spinler      * @brief Stops an in progress command
1473019c6fbSMatt Spinler      *
1483019c6fbSMatt Spinler      * In progress meaning after the send but before the response.
1493019c6fbSMatt Spinler      */
1503019c6fbSMatt Spinler     void stopCommand();
1513019c6fbSMatt Spinler 
1523019c6fbSMatt Spinler     /**
153f60ac27eSMatt Spinler      * @brief The PEL repository object
154f60ac27eSMatt Spinler      */
155f60ac27eSMatt Spinler     Repository& _repo;
156f60ac27eSMatt Spinler 
157f60ac27eSMatt Spinler     /**
158f60ac27eSMatt Spinler      * @brief The data interface object
159f60ac27eSMatt Spinler      */
160f60ac27eSMatt Spinler     DataInterfaceBase& _dataIface;
161f60ac27eSMatt Spinler 
162f60ac27eSMatt Spinler     /**
163f60ac27eSMatt Spinler      * @brief Base class pointer for the host command interface
164f60ac27eSMatt Spinler      */
165f60ac27eSMatt Spinler     std::unique_ptr<HostInterface> _hostIface;
166f60ac27eSMatt Spinler 
167f60ac27eSMatt Spinler     /**
168f60ac27eSMatt Spinler      * @brief The list of PEL IDs that need to be sent.
169f60ac27eSMatt Spinler      */
170f60ac27eSMatt Spinler     std::deque<uint32_t> _pelQueue;
171f869fcf8SMatt Spinler 
172f869fcf8SMatt Spinler     /**
173f869fcf8SMatt Spinler      * @brief The list of IDs that were sent, but not acked yet.
174f869fcf8SMatt Spinler      *
175f869fcf8SMatt Spinler      * These move back to _pelQueue on a power off.
176f869fcf8SMatt Spinler      */
177f869fcf8SMatt Spinler     std::vector<uint32_t> _sentPELs;
178f869fcf8SMatt Spinler 
179f869fcf8SMatt Spinler     /**
180f869fcf8SMatt Spinler      * @brief The ID the PEL where the notification has
181f869fcf8SMatt Spinler      *        been kicked off but the asynchronous response
182f869fcf8SMatt Spinler      *        hasn't been received yet.
183f869fcf8SMatt Spinler      */
184f869fcf8SMatt Spinler     uint32_t _inProgressPEL = 0;
185f869fcf8SMatt Spinler 
186f869fcf8SMatt Spinler     /**
187f869fcf8SMatt Spinler      * @brief The command retry count
188f869fcf8SMatt Spinler      */
189f869fcf8SMatt Spinler     size_t _retryCount = 0;
190f869fcf8SMatt Spinler 
191f869fcf8SMatt Spinler     /**
192f869fcf8SMatt Spinler      * @brief The command retry timer.
193f869fcf8SMatt Spinler      */
194f869fcf8SMatt Spinler     sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> _retryTimer;
195f60ac27eSMatt Spinler };
196f60ac27eSMatt Spinler 
197f60ac27eSMatt Spinler } // namespace openpower::pels
198