blob: 61bb2a4f603e8e69225da32bc292938185e26c42 [file] [log] [blame]
Matt Spinler5c350fd2019-12-12 13:53:53 -06001#pragma once
2
3#include "host_interface.hpp"
4
5#include <libpldm/pldm.h>
6
7#include <chrono>
8#include <memory>
9#include <sdeventplus/clock.hpp>
10#include <sdeventplus/source/io.hpp>
11#include <sdeventplus/utility/timer.hpp>
12
13namespace openpower::pels
14{
15
16/**
17 * @class PLDMInterface
18 *
19 * This class handles sending the 'new file available' PLDM
20 * command to the host to notify it of a new PEL's ID and size.
21 *
22 * The command response is asynchronous.
23 */
24class PLDMInterface : public HostInterface
25{
26 public:
27 PLDMInterface() = delete;
28 PLDMInterface(const PLDMInterface&) = default;
29 PLDMInterface& operator=(const PLDMInterface&) = default;
30 PLDMInterface(PLDMInterface&&) = default;
31 PLDMInterface& operator=(PLDMInterface&&) = default;
32
33 /**
34 * @brief Constructor
35 *
36 * @param[in] event - The sd_event object pointer
37 * @param[in] dataIface - The DataInterface object
38 */
39 PLDMInterface(sd_event* event, DataInterfaceBase& dataIface) :
40 HostInterface(event, dataIface),
41 _receiveTimer(
42 event,
43 std::bind(std::mem_fn(&PLDMInterface::receiveTimerExpired), this))
44 {
Matt Spinler2843ba22020-03-03 16:36:32 -060045 sd_bus_default(&_bus);
46
Matt Spinler5c350fd2019-12-12 13:53:53 -060047 readEID();
48 }
49
50 /**
51 * @brief Destructor
52 */
53 ~PLDMInterface();
54
55 /**
56 * @brief Kicks off the send of the 'new file available' command
57 * to send up the ID and size of the new PEL.
58 *
Matt Spinler2843ba22020-03-03 16:36:32 -060059 * It starts by issuing the async D-Bus method call to read the
60 * instance ID.
61 *
Matt Spinler5c350fd2019-12-12 13:53:53 -060062 * @param[in] id - The PEL ID
63 * @param[in] size - The PEL size in bytes
64 *
65 * @return CmdStatus - the success/fail status of the send
66 */
67 CmdStatus sendNewLogCmd(uint32_t id, uint32_t size) override;
68
69 /**
70 * @brief Cancels waiting for a command response
Matt Spinler2843ba22020-03-03 16:36:32 -060071 *
72 * This will clear the instance ID so the next command
73 * will request a new one.
Matt Spinler5c350fd2019-12-12 13:53:53 -060074 */
75 void cancelCmd() override;
76
Matt Spinler2843ba22020-03-03 16:36:32 -060077 /**
78 * @brief Cleans up so that a new command is ready to be sent.
79 *
80 * Does not clear the instance ID.
81 */
82 void cleanupCmd();
83
84 /**
85 * @brief Gets called on the async D-Bus method response to
86 * getting the PLDM instance ID.
87 *
88 * It will read the instance ID out of the message and then
89 * continue on with sending the new log command to the host.
90 *
91 * @param[in] msg - The message containing the instance ID.
92 */
93 void instanceIDCallback(sd_bus_message* msg);
94
Matt Spinler5c350fd2019-12-12 13:53:53 -060095 private:
96 /**
97 * @brief The asynchronous callback for getting the response
98 * of the 'new file available' command.
99 *
100 * Calls the response callback that is registered.
101 *
102 * @param[in] io - The event source object
103 * @param[in] fd - The FD used
104 * @param[in] revents - The event bits
105 */
106 void receive(sdeventplus::source::IO& io, int fd,
107 uint32_t revents) override;
108
109 /**
110 * @brief Function called when the receive timer expires.
111 *
112 * This is considered a failure and so will invoke the
113 * registered response callback function with a failure
114 * indication.
115 */
116 void receiveTimerExpired();
117
118 /**
119 * @brief Configures the sdeventplus::source::IO object to
120 * call receive() on EPOLLIN activity on the PLDM FD
121 * which is used for command responses.
122 */
123 void registerReceiveCallback();
124
125 /**
126 * @brief Reads the MCTP endpoint ID out of a file
127 */
128 void readEID();
129
130 /**
131 * @brief Opens the PLDM file descriptor
132 */
133 void open();
134
135 /**
Matt Spinler2843ba22020-03-03 16:36:32 -0600136 * @brief Makes the async D-Bus method call to read the PLDM instance
137 * ID needed to send PLDM commands.
Matt Spinler5c350fd2019-12-12 13:53:53 -0600138 */
Matt Spinler2843ba22020-03-03 16:36:32 -0600139 void startReadInstanceID();
Matt Spinler5c350fd2019-12-12 13:53:53 -0600140
141 /**
142 * @brief Encodes and sends the PLDM 'new file available' cmd
Matt Spinler5c350fd2019-12-12 13:53:53 -0600143 */
Matt Spinler2843ba22020-03-03 16:36:32 -0600144 void doSend();
Matt Spinler5c350fd2019-12-12 13:53:53 -0600145
146 /**
147 * @brief Closes the PLDM file descriptor
148 */
149 void closeFD();
150
151 /**
Matt Spinler2843ba22020-03-03 16:36:32 -0600152 * @brief Kicks off the send of the 'new file available' command
153 * to send the ID and size of a PEL after the instance ID
154 * has been retrieved.
155 */
156 void startCommand();
157
158 /**
Matt Spinler5c350fd2019-12-12 13:53:53 -0600159 * @brief The MCTP endpoint ID
160 */
161 mctp_eid_t _eid;
162
163 /**
164 * @brief The PLDM instance ID of the current command
Matt Spinler2843ba22020-03-03 16:36:32 -0600165 *
166 * A new ID will be used for every command.
167 *
168 * If there are command failures, the same instance ID can be
169 * used on retries only if the host didn't respond.
Matt Spinler5c350fd2019-12-12 13:53:53 -0600170 */
Matt Spinler2843ba22020-03-03 16:36:32 -0600171 std::optional<uint8_t> _instanceID;
Matt Spinler5c350fd2019-12-12 13:53:53 -0600172
173 /**
174 * @brief The PLDM command file descriptor for the current command
175 */
176 int _fd = -1;
177
178 /**
179 * @brief The event object for handling callbacks on the PLDM FD
180 */
181 std::unique_ptr<sdeventplus::source::IO> _source;
182
183 /**
184 * @brief A timer to only allow a certain amount of time for the
185 * async PLDM receive before it is considered a failure.
186 */
187 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> _receiveTimer;
188
189 /**
190 * @brief The command timeout value
191 */
192 const std::chrono::milliseconds _receiveTimeout{10000};
Matt Spinler2843ba22020-03-03 16:36:32 -0600193
194 /**
195 * @brief The D-Bus connection needed for the async method call.
196 */
197 sd_bus* _bus = nullptr;
198
199 /**
200 * @brief The ID of the PEL to notify the host of.
201 */
202 uint32_t _pelID = 0;
203
204 /**
205 * @brief The size of the PEL to notify the host of.
206 */
207 uint32_t _pelSize = 0;
Matt Spinler5c350fd2019-12-12 13:53:53 -0600208};
209
210} // namespace openpower::pels