summaryrefslogtreecommitdiffstats
path: root/extensions/openpower-pels/pldm_interface.hpp
blob: 0d679a142f2b8a1af086e2320fa8ce7ce475d056 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#pragma once

#include "host_interface.hpp"

#include <libpldm/pldm.h>

#include <chrono>
#include <memory>
#include <sdeventplus/clock.hpp>
#include <sdeventplus/source/io.hpp>
#include <sdeventplus/utility/timer.hpp>

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))
    {
        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.
     *
     * @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
     */
    void cancelCmd() override;

  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
     */
    void receive(sdeventplus::source::IO& io, int fd,
                 uint32_t revents) 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 Reads the PLDM instance ID to use for the upcoming
     *        command.
     */
    void readInstanceID();

    /**
     * @brief Encodes and sends the PLDM 'new file available' cmd
     *
     * @param[in] id - The PEL ID
     * @param[in] size - The PEL size in bytes
     */
    void doSend(uint32_t id, uint32_t size);

    /**
     * @brief Closes the PLDM file descriptor
     */
    void closeFD();

    /**
     * @brief The MCTP endpoint ID
     */
    mctp_eid_t _eid;

    /**
     * @brief The PLDM instance ID of the current command
     */
    uint8_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{10000};
};

} // namespace openpower::pels
OpenPOWER on IntegriCloud