| #pragma once |
| |
| #include "host_interface.hpp" |
| |
| #include <libpldm/instance-id.h> |
| #include <libpldm/pldm.h> |
| #include <libpldm/transport.h> |
| #include <libpldm/transport/mctp-demux.h> |
| |
| #include <sdeventplus/clock.hpp> |
| #include <sdeventplus/source/io.hpp> |
| #include <sdeventplus/utility/timer.hpp> |
| |
| #include <chrono> |
| #include <memory> |
| |
| namespace openpower::pels |
| { |
| |
| /** |
| * @class PLDMInterface |
| * |
| * This class handles sending the 'new file available' PLDM |
| * command to the host to notify it of a new PEL's ID and size. |
| * |
| * The command response is asynchronous. |
| */ |
| class PLDMInterface : public HostInterface |
| { |
| public: |
| PLDMInterface() = delete; |
| PLDMInterface(const PLDMInterface&) = default; |
| PLDMInterface& operator=(const PLDMInterface&) = default; |
| PLDMInterface(PLDMInterface&&) = default; |
| PLDMInterface& operator=(PLDMInterface&&) = default; |
| |
| /** |
| * @brief Constructor |
| * |
| * @param[in] event - The sd_event object pointer |
| * @param[in] dataIface - The DataInterface object |
| */ |
| PLDMInterface(sd_event* event, DataInterfaceBase& dataIface) : |
| HostInterface(event, dataIface), |
| _receiveTimer( |
| event, |
| std::bind(std::mem_fn(&PLDMInterface::receiveTimerExpired), this)) |
| { |
| pldm_instance_db_init_default(&_pldm_idb); |
| |
| readEID(); |
| } |
| |
| /** |
| * @brief Destructor |
| */ |
| ~PLDMInterface(); |
| |
| /** |
| * @brief Kicks off the send of the 'new file available' command |
| * to send up the ID and size of the new PEL. |
| * |
| * It starts by issuing the async D-Bus method call to read the |
| * instance ID. |
| * |
| * @param[in] id - The PEL ID |
| * @param[in] size - The PEL size in bytes |
| * |
| * @return CmdStatus - the success/fail status of the send |
| */ |
| CmdStatus sendNewLogCmd(uint32_t id, uint32_t size) override; |
| |
| /** |
| * @brief Cancels waiting for a command response |
| * |
| * This will clear the instance ID so the next command |
| * will request a new one. |
| */ |
| void cancelCmd() override; |
| |
| /** |
| * @brief Cleans up so that a new command is ready to be sent. |
| * |
| * Does not clear the instance ID. |
| */ |
| void cleanupCmd(); |
| |
| private: |
| /** |
| * @brief The asynchronous callback for getting the response |
| * of the 'new file available' command. |
| * |
| * Calls the response callback that is registered. |
| * |
| * @param[in] io - The event source object |
| * @param[in] fd - The FD used |
| * @param[in] revents - The event bits |
| * @param[in] transport - The transport data pointer |
| */ |
| void receive(sdeventplus::source::IO& io, int fd, uint32_t revents, |
| pldm_transport* transport) override; |
| |
| /** |
| * @brief Function called when the receive timer expires. |
| * |
| * This is considered a failure and so will invoke the |
| * registered response callback function with a failure |
| * indication. |
| */ |
| void receiveTimerExpired(); |
| |
| /** |
| * @brief Configures the sdeventplus::source::IO object to |
| * call receive() on EPOLLIN activity on the PLDM FD |
| * which is used for command responses. |
| */ |
| void registerReceiveCallback(); |
| |
| /** |
| * @brief Reads the MCTP endpoint ID out of a file |
| */ |
| void readEID(); |
| |
| /** |
| * @brief Opens the PLDM file descriptor |
| */ |
| void open(); |
| |
| /** @brief Opens the MCTP socket for sending and receiving messages. |
| * |
| */ |
| int openMctpDemuxTransport(); |
| |
| /** |
| * @brief Encodes and sends the PLDM 'new file available' cmd |
| */ |
| void doSend(); |
| |
| /** |
| * @brief Closes the PLDM file descriptor |
| */ |
| void closeFD(); |
| |
| /** |
| * @brief Kicks off the send of the 'new file available' command |
| * to send the ID and size of a PEL after the instance ID |
| * has been retrieved. |
| */ |
| void startCommand(); |
| |
| /** |
| * @brief Allocates the instance id. |
| */ |
| void allocIID(); |
| |
| /** |
| * @brief Frees the instance id. |
| */ |
| void freeIID(); |
| |
| /** |
| * @brief The MCTP endpoint ID |
| */ |
| mctp_eid_t _eid; |
| |
| /** |
| * @brief The PLDM instance ID of the current command |
| * |
| * A new ID will be used for every command. |
| * |
| * If there are command failures, the same instance ID can be |
| * used on retries only if the host didn't respond. |
| */ |
| std::optional<pldm_instance_id_t> _instanceID; |
| |
| /** |
| * @brief The PLDM command file descriptor for the current command |
| */ |
| int _fd = -1; |
| |
| /** |
| * @brief The event object for handling callbacks on the PLDM FD |
| */ |
| std::unique_ptr<sdeventplus::source::IO> _source; |
| |
| /** |
| * @brief A timer to only allow a certain amount of time for the |
| * async PLDM receive before it is considered a failure. |
| */ |
| sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> _receiveTimer; |
| |
| /** |
| * @brief The command timeout value |
| */ |
| const std::chrono::milliseconds _receiveTimeout{45000}; |
| |
| /** |
| * @brief The libpldm instance ID database. |
| */ |
| pldm_instance_db* _pldm_idb = nullptr; |
| |
| /** |
| * @brief The ID of the PEL to notify the host of. |
| */ |
| uint32_t _pelID = 0; |
| |
| /** |
| * @brief The size of the PEL to notify the host of. |
| */ |
| uint32_t _pelSize = 0; |
| |
| /** |
| * @brief pldm transport instance. |
| */ |
| pldm_transport* pldmTransport = nullptr; |
| |
| pldm_transport_mctp_demux* mctpDemux = nullptr; |
| }; |
| |
| } // namespace openpower::pels |