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> 97d800a4eSMatt Spinler #include <sdeventplus/source/event.hpp> 10f869fcf8SMatt Spinler #include <sdeventplus/utility/timer.hpp> 11f60ac27eSMatt Spinler 12f60ac27eSMatt Spinler namespace openpower::pels 13f60ac27eSMatt Spinler { 14f60ac27eSMatt Spinler 15f60ac27eSMatt Spinler /** 16f60ac27eSMatt Spinler * @class HostNotifier 17f60ac27eSMatt Spinler * 18f60ac27eSMatt Spinler * This class handles notifying the host firmware of new PELs. 19f60ac27eSMatt Spinler */ 20f60ac27eSMatt Spinler class HostNotifier 21f60ac27eSMatt Spinler { 22f60ac27eSMatt Spinler public: 23f60ac27eSMatt Spinler HostNotifier() = delete; 24f60ac27eSMatt Spinler HostNotifier(const HostNotifier&) = delete; 25f60ac27eSMatt Spinler HostNotifier& operator=(const HostNotifier&) = delete; 26f60ac27eSMatt Spinler HostNotifier(HostNotifier&&) = delete; 27f60ac27eSMatt Spinler HostNotifier& operator=(HostNotifier&&) = delete; 28f60ac27eSMatt Spinler 29f60ac27eSMatt Spinler /** 30f60ac27eSMatt Spinler * @brief Constructor 31f60ac27eSMatt Spinler * 32f60ac27eSMatt Spinler * @param[in] repo - The PEL repository object 33f60ac27eSMatt Spinler * @param[in] dataIface - The data interface object 34f60ac27eSMatt Spinler * @param[in] hostIface - The host interface object 35f60ac27eSMatt Spinler */ 36f60ac27eSMatt Spinler HostNotifier(Repository& repo, DataInterfaceBase& dataIface, 37f60ac27eSMatt Spinler std::unique_ptr<HostInterface> hostIface); 38f60ac27eSMatt Spinler 39f60ac27eSMatt Spinler /** 40f60ac27eSMatt Spinler * @brief Destructor 41f60ac27eSMatt Spinler */ 42f60ac27eSMatt Spinler ~HostNotifier(); 43f60ac27eSMatt Spinler 44f60ac27eSMatt Spinler /** 45f60ac27eSMatt Spinler * @brief Returns the PEL queue size. 46f60ac27eSMatt Spinler * 47f60ac27eSMatt Spinler * For testing. 48f60ac27eSMatt Spinler * 49f60ac27eSMatt Spinler * @return size_t - The queue size 50f60ac27eSMatt Spinler */ 51f60ac27eSMatt Spinler size_t queueSize() const 52f60ac27eSMatt Spinler { 53f60ac27eSMatt Spinler return _pelQueue.size(); 54f60ac27eSMatt Spinler } 55f60ac27eSMatt Spinler 56f60ac27eSMatt Spinler /** 57f60ac27eSMatt Spinler * @brief Specifies if the PEL needs to go onto the queue to be 58f60ac27eSMatt Spinler * set to the host. 59f60ac27eSMatt Spinler * 60a943b15bSMatt Spinler * Only returns false if: 61a943b15bSMatt Spinler * - Already acked by the host (or they didn't like it) 62a943b15bSMatt Spinler * - Hidden and the HMC already got it 63a943b15bSMatt Spinler * - The 'do not report to host' bit is set 64a943b15bSMatt Spinler * 65f60ac27eSMatt Spinler * @param[in] id - The PEL ID 66f60ac27eSMatt Spinler * 67f60ac27eSMatt Spinler * @return bool - If enqueue is required 68f60ac27eSMatt Spinler */ 69f60ac27eSMatt Spinler bool enqueueRequired(uint32_t id) const; 70f60ac27eSMatt Spinler 71f77debb9SMatt Spinler /** 72f77debb9SMatt Spinler * @brief If the host still needs to be notified of the PEL 73f77debb9SMatt Spinler * at the time of the notification. 74f77debb9SMatt Spinler * 75f77debb9SMatt Spinler * Only returns false if: 76f77debb9SMatt Spinler * - Already acked by the host 77f77debb9SMatt Spinler * - It's hidden, and the HMC already got or will get it. 78f77debb9SMatt Spinler * 79f77debb9SMatt Spinler * @param[in] id - The PEL ID 80f77debb9SMatt Spinler * 81f77debb9SMatt Spinler * @return bool - If the notify is required 82f77debb9SMatt Spinler */ 83f77debb9SMatt Spinler bool notifyRequired(uint32_t id) const; 84f77debb9SMatt Spinler 85*cc3b64aeSMatt Spinler /** 86*cc3b64aeSMatt Spinler * @brief Called when the host sends the 'ack' PLDM command. 87*cc3b64aeSMatt Spinler * 88*cc3b64aeSMatt Spinler * This means the PEL never needs to be sent up again. 89*cc3b64aeSMatt Spinler * 90*cc3b64aeSMatt Spinler * @param[in] id - The PEL ID 91*cc3b64aeSMatt Spinler */ 92*cc3b64aeSMatt Spinler void ackPEL(uint32_t id); 93*cc3b64aeSMatt Spinler 94f60ac27eSMatt Spinler private: 95f60ac27eSMatt Spinler /** 96f60ac27eSMatt Spinler * @brief This function gets called by the Repository class 97f60ac27eSMatt Spinler * when a new PEL is added to it. 98f60ac27eSMatt Spinler * 997d800a4eSMatt Spinler * This function puts the PEL on the queue to be sent up if it 1007d800a4eSMatt Spinler * needs it, and possibly dispatch the send if the conditions call 1017d800a4eSMatt Spinler * for it. 1027d800a4eSMatt Spinler * 103f60ac27eSMatt Spinler * @param[in] pel - The new PEL 104f60ac27eSMatt Spinler */ 105f60ac27eSMatt Spinler void newLogCallback(const PEL& pel); 106f60ac27eSMatt Spinler 107f60ac27eSMatt Spinler /** 108f60ac27eSMatt Spinler * @brief This function runs on every existing PEL at startup 109f60ac27eSMatt Spinler * and puts the PEL on the queue to send if necessary. 110f60ac27eSMatt Spinler * 111f60ac27eSMatt Spinler * @param[in] pel - The PEL 112f60ac27eSMatt Spinler * 113f60ac27eSMatt Spinler * @return bool - This is an indicator to the Repository::for_each 114f60ac27eSMatt Spinler * function to traverse every PEL. Always false. 115f60ac27eSMatt Spinler */ 116f60ac27eSMatt Spinler bool addPELToQueue(const PEL& pel); 117f60ac27eSMatt Spinler 118f60ac27eSMatt Spinler /** 119f77debb9SMatt Spinler * @brief Takes the first PEL from the queue that needs to be 120f77debb9SMatt Spinler * sent, and issues the send if conditions are right. 121f60ac27eSMatt Spinler */ 122f60ac27eSMatt Spinler void doNewLogNotify(); 123f60ac27eSMatt Spinler 124f60ac27eSMatt Spinler /** 1257d800a4eSMatt Spinler * @brief Creates the event object to handle sending the PLDM 1267d800a4eSMatt Spinler * command from the event loop. 1277d800a4eSMatt Spinler */ 1287d800a4eSMatt Spinler void scheduleDispatch(); 1297d800a4eSMatt Spinler 1307d800a4eSMatt Spinler /** 1317d800a4eSMatt Spinler * @brief Kicks off the PLDM send, but called from the event 1327d800a4eSMatt Spinler * loop. 1337d800a4eSMatt Spinler * 1347d800a4eSMatt Spinler * @param[in] source - The event source object 1357d800a4eSMatt Spinler */ 1367d800a4eSMatt Spinler void dispatch(sdeventplus::source::EventBase& source); 1377d800a4eSMatt Spinler 1387d800a4eSMatt Spinler /** 139f60ac27eSMatt Spinler * @brief Called when the host changes state. 140f60ac27eSMatt Spinler * 1413019c6fbSMatt Spinler * If the new state is host up and there are PELs to send, it 1423019c6fbSMatt Spinler * will trigger the first command. If the new state is off, then 1433019c6fbSMatt Spinler * it will transfer any PELs that were sent but not acked yet back 1443019c6fbSMatt Spinler * to the queue to be sent again. 1453019c6fbSMatt Spinler * 146f60ac27eSMatt Spinler * @param[in] hostUp - The new host state 147f60ac27eSMatt Spinler */ 148f60ac27eSMatt Spinler void hostStateChange(bool hostUp); 149f60ac27eSMatt Spinler 150f60ac27eSMatt Spinler /** 151f60ac27eSMatt Spinler * @brief The callback function invoked after the asynchronous 152f60ac27eSMatt Spinler * PLDM receive function is complete. 153f60ac27eSMatt Spinler * 154f869fcf8SMatt Spinler * If the command was successful, the state of that PEL will 155f869fcf8SMatt Spinler * be set to 'sent', and the next send will be triggered. 156f869fcf8SMatt Spinler * 157f869fcf8SMatt Spinler * If the command failed, a retry timer will be started so it 158f869fcf8SMatt Spinler * can be sent again. 159f869fcf8SMatt Spinler * 160f60ac27eSMatt Spinler * @param[in] status - The response status 161f60ac27eSMatt Spinler */ 162f60ac27eSMatt Spinler void commandResponse(ResponseStatus status); 163f60ac27eSMatt Spinler 164f60ac27eSMatt Spinler /** 165f869fcf8SMatt Spinler * @brief The function called when the command failure retry 166f869fcf8SMatt Spinler * time is up. 167f869fcf8SMatt Spinler * 168f869fcf8SMatt Spinler * It will issue a send of the previous PEL and increment the 169f869fcf8SMatt Spinler * retry count. 170f869fcf8SMatt Spinler */ 171f869fcf8SMatt Spinler void retryTimerExpired(); 172f869fcf8SMatt Spinler 173f869fcf8SMatt Spinler /** 1743019c6fbSMatt Spinler * @brief Stops an in progress command 1753019c6fbSMatt Spinler * 1763019c6fbSMatt Spinler * In progress meaning after the send but before the response. 1773019c6fbSMatt Spinler */ 1783019c6fbSMatt Spinler void stopCommand(); 1793019c6fbSMatt Spinler 1803019c6fbSMatt Spinler /** 181f60ac27eSMatt Spinler * @brief The PEL repository object 182f60ac27eSMatt Spinler */ 183f60ac27eSMatt Spinler Repository& _repo; 184f60ac27eSMatt Spinler 185f60ac27eSMatt Spinler /** 186f60ac27eSMatt Spinler * @brief The data interface object 187f60ac27eSMatt Spinler */ 188f60ac27eSMatt Spinler DataInterfaceBase& _dataIface; 189f60ac27eSMatt Spinler 190f60ac27eSMatt Spinler /** 191f60ac27eSMatt Spinler * @brief Base class pointer for the host command interface 192f60ac27eSMatt Spinler */ 193f60ac27eSMatt Spinler std::unique_ptr<HostInterface> _hostIface; 194f60ac27eSMatt Spinler 195f60ac27eSMatt Spinler /** 196f60ac27eSMatt Spinler * @brief The list of PEL IDs that need to be sent. 197f60ac27eSMatt Spinler */ 198f60ac27eSMatt Spinler std::deque<uint32_t> _pelQueue; 199f869fcf8SMatt Spinler 200f869fcf8SMatt Spinler /** 201f869fcf8SMatt Spinler * @brief The list of IDs that were sent, but not acked yet. 202f869fcf8SMatt Spinler * 203f869fcf8SMatt Spinler * These move back to _pelQueue on a power off. 204f869fcf8SMatt Spinler */ 205f869fcf8SMatt Spinler std::vector<uint32_t> _sentPELs; 206f869fcf8SMatt Spinler 207f869fcf8SMatt Spinler /** 208f869fcf8SMatt Spinler * @brief The ID the PEL where the notification has 209f869fcf8SMatt Spinler * been kicked off but the asynchronous response 210f869fcf8SMatt Spinler * hasn't been received yet. 211f869fcf8SMatt Spinler */ 212f869fcf8SMatt Spinler uint32_t _inProgressPEL = 0; 213f869fcf8SMatt Spinler 214f869fcf8SMatt Spinler /** 215f869fcf8SMatt Spinler * @brief The command retry count 216f869fcf8SMatt Spinler */ 217f869fcf8SMatt Spinler size_t _retryCount = 0; 218f869fcf8SMatt Spinler 219f869fcf8SMatt Spinler /** 220f869fcf8SMatt Spinler * @brief The command retry timer. 221f869fcf8SMatt Spinler */ 222f869fcf8SMatt Spinler sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> _retryTimer; 2237d800a4eSMatt Spinler 2247d800a4eSMatt Spinler /** 2257d800a4eSMatt Spinler * @brief The object used to dispatch a new PEL send from the 2267d800a4eSMatt Spinler * event loop, so the calling function can be returned from 2277d800a4eSMatt Spinler * first. 2287d800a4eSMatt Spinler */ 2297d800a4eSMatt Spinler std::unique_ptr<sdeventplus::source::Defer> _dispatcher; 230f60ac27eSMatt Spinler }; 231f60ac27eSMatt Spinler 232f60ac27eSMatt Spinler } // namespace openpower::pels 233