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