1f60ac27eSMatt Spinler /** 2f60ac27eSMatt Spinler * Copyright © 2019 IBM Corporation 3f60ac27eSMatt Spinler * 4f60ac27eSMatt Spinler * Licensed under the Apache License, Version 2.0 (the "License"); 5f60ac27eSMatt Spinler * you may not use this file except in compliance with the License. 6f60ac27eSMatt Spinler * You may obtain a copy of the License at 7f60ac27eSMatt Spinler * 8f60ac27eSMatt Spinler * http://www.apache.org/licenses/LICENSE-2.0 9f60ac27eSMatt Spinler * 10f60ac27eSMatt Spinler * Unless required by applicable law or agreed to in writing, software 11f60ac27eSMatt Spinler * distributed under the License is distributed on an "AS IS" BASIS, 12f60ac27eSMatt Spinler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f60ac27eSMatt Spinler * See the License for the specific language governing permissions and 14f60ac27eSMatt Spinler * limitations under the License. 15f60ac27eSMatt Spinler */ 16f60ac27eSMatt Spinler #include "host_notifier.hpp" 17f60ac27eSMatt Spinler 18f60ac27eSMatt Spinler #include <phosphor-logging/log.hpp> 19f60ac27eSMatt Spinler 20f60ac27eSMatt Spinler namespace openpower::pels 21f60ac27eSMatt Spinler { 22f60ac27eSMatt Spinler 23f60ac27eSMatt Spinler const auto subscriptionName = "PELHostNotifier"; 24f77debb9SMatt Spinler const size_t maxRetryAttempts = 15; 25f60ac27eSMatt Spinler 26f60ac27eSMatt Spinler using namespace phosphor::logging; 27f60ac27eSMatt Spinler 28f60ac27eSMatt Spinler HostNotifier::HostNotifier(Repository& repo, DataInterfaceBase& dataIface, 29f60ac27eSMatt Spinler std::unique_ptr<HostInterface> hostIface) : 30f60ac27eSMatt Spinler _repo(repo), 31f869fcf8SMatt Spinler _dataIface(dataIface), _hostIface(std::move(hostIface)), 32f869fcf8SMatt Spinler _retryTimer(_hostIface->getEvent(), 3341293cb8SMatt Spinler std::bind(std::mem_fn(&HostNotifier::retryTimerExpired), this)), 3441293cb8SMatt Spinler _hostFullTimer( 3541293cb8SMatt Spinler _hostIface->getEvent(), 3641293cb8SMatt Spinler std::bind(std::mem_fn(&HostNotifier::hostFullTimerExpired), this)) 37f60ac27eSMatt Spinler { 38f60ac27eSMatt Spinler // Subscribe to be told about new PELs. 39f60ac27eSMatt Spinler _repo.subscribeToAdds(subscriptionName, 40f60ac27eSMatt Spinler std::bind(std::mem_fn(&HostNotifier::newLogCallback), 41f60ac27eSMatt Spinler this, std::placeholders::_1)); 42f60ac27eSMatt Spinler 43f60ac27eSMatt Spinler // Add any existing PELs to the queue to send them if necessary. 44f60ac27eSMatt Spinler _repo.for_each(std::bind(std::mem_fn(&HostNotifier::addPELToQueue), this, 45f60ac27eSMatt Spinler std::placeholders::_1)); 46f60ac27eSMatt Spinler 47f60ac27eSMatt Spinler // Subscribe to be told about host state changes. 48f60ac27eSMatt Spinler _dataIface.subscribeToHostStateChange( 49f60ac27eSMatt Spinler subscriptionName, 50f60ac27eSMatt Spinler std::bind(std::mem_fun(&HostNotifier::hostStateChange), this, 51f60ac27eSMatt Spinler std::placeholders::_1)); 52f60ac27eSMatt Spinler 53f60ac27eSMatt Spinler // Set the function to call when the async reponse is received. 54f60ac27eSMatt Spinler _hostIface->setResponseFunction( 55f60ac27eSMatt Spinler std::bind(std::mem_fn(&HostNotifier::commandResponse), this, 56f60ac27eSMatt Spinler std::placeholders::_1)); 57f60ac27eSMatt Spinler 58f60ac27eSMatt Spinler // Start sending logs if the host is running 59f60ac27eSMatt Spinler if (!_pelQueue.empty() && _dataIface.isHostUp()) 60f60ac27eSMatt Spinler { 61f60ac27eSMatt Spinler doNewLogNotify(); 62f60ac27eSMatt Spinler } 63f60ac27eSMatt Spinler } 64f60ac27eSMatt Spinler 65f60ac27eSMatt Spinler HostNotifier::~HostNotifier() 66f60ac27eSMatt Spinler { 67f60ac27eSMatt Spinler _repo.unsubscribeFromAdds(subscriptionName); 68f60ac27eSMatt Spinler _dataIface.unsubscribeFromHostStateChange(subscriptionName); 69f60ac27eSMatt Spinler } 70f60ac27eSMatt Spinler 71f60ac27eSMatt Spinler bool HostNotifier::addPELToQueue(const PEL& pel) 72f60ac27eSMatt Spinler { 73f60ac27eSMatt Spinler if (enqueueRequired(pel.id())) 74f60ac27eSMatt Spinler { 75f60ac27eSMatt Spinler _pelQueue.push_back(pel.id()); 76f60ac27eSMatt Spinler } 77f60ac27eSMatt Spinler 78f60ac27eSMatt Spinler // Return false so that Repo::for_each keeps going. 79f60ac27eSMatt Spinler return false; 80f60ac27eSMatt Spinler } 81f60ac27eSMatt Spinler 82f60ac27eSMatt Spinler bool HostNotifier::enqueueRequired(uint32_t id) const 83f60ac27eSMatt Spinler { 84f60ac27eSMatt Spinler bool required = true; 85a943b15bSMatt Spinler Repository::LogID i{Repository::LogID::Pel{id}}; 86a943b15bSMatt Spinler 8724a8558bSMatt Spinler // Manufacturing testing may turn off sending up PELs 8824a8558bSMatt Spinler if (!_dataIface.getHostPELEnablement()) 8924a8558bSMatt Spinler { 9024a8558bSMatt Spinler return false; 9124a8558bSMatt Spinler } 9224a8558bSMatt Spinler 93a943b15bSMatt Spinler if (auto attributes = _repo.getPELAttributes(i); attributes) 94a943b15bSMatt Spinler { 95a943b15bSMatt Spinler auto a = attributes.value().get(); 96a943b15bSMatt Spinler 97a943b15bSMatt Spinler if ((a.hostState == TransmissionState::acked) || 98a943b15bSMatt Spinler (a.hostState == TransmissionState::badPEL)) 99a943b15bSMatt Spinler { 100a943b15bSMatt Spinler required = false; 101a943b15bSMatt Spinler } 102a943b15bSMatt Spinler else if (a.actionFlags.test(hiddenFlagBit) && 103a943b15bSMatt Spinler (a.hmcState == TransmissionState::acked)) 104a943b15bSMatt Spinler { 105a943b15bSMatt Spinler required = false; 106a943b15bSMatt Spinler } 107a943b15bSMatt Spinler else if (a.actionFlags.test(dontReportToHostFlagBit)) 108a943b15bSMatt Spinler { 109a943b15bSMatt Spinler required = false; 110a943b15bSMatt Spinler } 111a943b15bSMatt Spinler } 112a943b15bSMatt Spinler else 113a943b15bSMatt Spinler { 114a943b15bSMatt Spinler using namespace phosphor::logging; 115a943b15bSMatt Spinler log<level::ERR>("Host Enqueue: Unable to find PEL ID in repository", 116a943b15bSMatt Spinler entry("PEL_ID=0x%X", id)); 117a943b15bSMatt Spinler required = false; 118a943b15bSMatt Spinler } 119f60ac27eSMatt Spinler 120f60ac27eSMatt Spinler return required; 121f60ac27eSMatt Spinler } 122f60ac27eSMatt Spinler 123f77debb9SMatt Spinler bool HostNotifier::notifyRequired(uint32_t id) const 124f77debb9SMatt Spinler { 125f77debb9SMatt Spinler bool notify = true; 126f77debb9SMatt Spinler Repository::LogID i{Repository::LogID::Pel{id}}; 127f77debb9SMatt Spinler 128f77debb9SMatt Spinler if (auto attributes = _repo.getPELAttributes(i); attributes) 129f77debb9SMatt Spinler { 130f77debb9SMatt Spinler // If already acked by the host, don't send again. 131f77debb9SMatt Spinler // (A safety check as it shouldn't get to this point.) 132f77debb9SMatt Spinler auto a = attributes.value().get(); 133f77debb9SMatt Spinler if (a.hostState == TransmissionState::acked) 134f77debb9SMatt Spinler { 135f77debb9SMatt Spinler notify = false; 136f77debb9SMatt Spinler } 137f77debb9SMatt Spinler else if (a.actionFlags.test(hiddenFlagBit)) 138f77debb9SMatt Spinler { 139f77debb9SMatt Spinler // If hidden and acked (or will be) acked by the HMC, 140f77debb9SMatt Spinler // also don't send it. (HMC management can come and 141f77debb9SMatt Spinler // go at any time) 142f77debb9SMatt Spinler if ((a.hmcState == TransmissionState::acked) || 143f77debb9SMatt Spinler _dataIface.isHMCManaged()) 144f77debb9SMatt Spinler { 145f77debb9SMatt Spinler notify = false; 146f77debb9SMatt Spinler } 147f77debb9SMatt Spinler } 148f77debb9SMatt Spinler } 149f77debb9SMatt Spinler else 150f77debb9SMatt Spinler { 151f77debb9SMatt Spinler // Must have been deleted since put on the queue. 152f77debb9SMatt Spinler notify = false; 153f77debb9SMatt Spinler } 154f77debb9SMatt Spinler 155f77debb9SMatt Spinler return notify; 156f77debb9SMatt Spinler } 157f77debb9SMatt Spinler 158f60ac27eSMatt Spinler void HostNotifier::newLogCallback(const PEL& pel) 159f60ac27eSMatt Spinler { 160f60ac27eSMatt Spinler if (!enqueueRequired(pel.id())) 161f60ac27eSMatt Spinler { 162f60ac27eSMatt Spinler return; 163f60ac27eSMatt Spinler } 164f60ac27eSMatt Spinler 165f60ac27eSMatt Spinler _pelQueue.push_back(pel.id()); 166f60ac27eSMatt Spinler 16741293cb8SMatt Spinler // Notify shouldn't happen if host is down or full 16841293cb8SMatt Spinler if (!_dataIface.isHostUp() || _hostFull) 1697d800a4eSMatt Spinler { 1707d800a4eSMatt Spinler return; 1717d800a4eSMatt Spinler } 1727d800a4eSMatt Spinler 1737d800a4eSMatt Spinler // Dispatch a command now if there isn't currently a command 1747d800a4eSMatt Spinler // in progress and this is the first log in the queue or it 1757d800a4eSMatt Spinler // previously gave up from a hard failure. 1767d800a4eSMatt Spinler auto inProgress = (_inProgressPEL != 0) || _hostIface->cmdInProgress() || 1777d800a4eSMatt Spinler _retryTimer.isEnabled(); 1787d800a4eSMatt Spinler 1797d800a4eSMatt Spinler auto firstPEL = _pelQueue.size() == 1; 1807d800a4eSMatt Spinler auto gaveUp = _retryCount >= maxRetryAttempts; 1817d800a4eSMatt Spinler 1827d800a4eSMatt Spinler if (!inProgress && (firstPEL || gaveUp)) 1837d800a4eSMatt Spinler { 1847d800a4eSMatt Spinler _retryCount = 0; 1857d800a4eSMatt Spinler 1867d800a4eSMatt Spinler // Send a log, but from the event loop, not from here. 1877d800a4eSMatt Spinler scheduleDispatch(); 1887d800a4eSMatt Spinler } 1897d800a4eSMatt Spinler } 1907d800a4eSMatt Spinler 1917d800a4eSMatt Spinler void HostNotifier::scheduleDispatch() 1927d800a4eSMatt Spinler { 1937d800a4eSMatt Spinler _dispatcher = std::make_unique<sdeventplus::source::Defer>( 1947d800a4eSMatt Spinler _hostIface->getEvent(), std::bind(std::mem_fn(&HostNotifier::dispatch), 1957d800a4eSMatt Spinler this, std::placeholders::_1)); 1967d800a4eSMatt Spinler } 1977d800a4eSMatt Spinler 1987d800a4eSMatt Spinler void HostNotifier::dispatch(sdeventplus::source::EventBase& source) 1997d800a4eSMatt Spinler { 2007d800a4eSMatt Spinler _dispatcher.reset(); 2017d800a4eSMatt Spinler 2027d800a4eSMatt Spinler doNewLogNotify(); 203f60ac27eSMatt Spinler } 204f60ac27eSMatt Spinler 205f60ac27eSMatt Spinler void HostNotifier::doNewLogNotify() 206f60ac27eSMatt Spinler { 20741293cb8SMatt Spinler if (!_dataIface.isHostUp() || _retryTimer.isEnabled() || 20841293cb8SMatt Spinler _hostFullTimer.isEnabled()) 209f77debb9SMatt Spinler { 210f77debb9SMatt Spinler return; 211f77debb9SMatt Spinler } 212f77debb9SMatt Spinler 213f77debb9SMatt Spinler if (_retryCount >= maxRetryAttempts) 214f77debb9SMatt Spinler { 215f77debb9SMatt Spinler // Give up until a new log comes in. 216f77debb9SMatt Spinler if (_retryCount == maxRetryAttempts) 217f77debb9SMatt Spinler { 218f77debb9SMatt Spinler // If this were to really happen, the PLDM interface 219f77debb9SMatt Spinler // would be down and isolating that shouldn't left to 220f77debb9SMatt Spinler // a logging daemon, so just trace. Also, this will start 221f77debb9SMatt Spinler // trying again when the next new log comes in. 222f77debb9SMatt Spinler log<level::ERR>( 223f77debb9SMatt Spinler "PEL Host notifier hit max retry attempts. Giving up for now.", 224f77debb9SMatt Spinler entry("PEL_ID=0x%X", _pelQueue.front())); 225*829b052dSMatt Spinler 226*829b052dSMatt Spinler // Tell the host interface object to clean itself up, especially to 227*829b052dSMatt Spinler // release the PLDM instance ID it's been using. 228*829b052dSMatt Spinler _hostIface->cancelCmd(); 229f77debb9SMatt Spinler } 230f77debb9SMatt Spinler return; 231f77debb9SMatt Spinler } 232f77debb9SMatt Spinler 233f77debb9SMatt Spinler bool doNotify = false; 234f77debb9SMatt Spinler uint32_t id = 0; 235f77debb9SMatt Spinler 236f77debb9SMatt Spinler // Find the PEL to send 237f77debb9SMatt Spinler while (!doNotify && !_pelQueue.empty()) 238f77debb9SMatt Spinler { 239f77debb9SMatt Spinler id = _pelQueue.front(); 240f77debb9SMatt Spinler _pelQueue.pop_front(); 241f77debb9SMatt Spinler 242f77debb9SMatt Spinler if (notifyRequired(id)) 243f77debb9SMatt Spinler { 244f77debb9SMatt Spinler doNotify = true; 245f77debb9SMatt Spinler } 246f77debb9SMatt Spinler } 247f77debb9SMatt Spinler 248f77debb9SMatt Spinler if (doNotify) 249f77debb9SMatt Spinler { 250f77debb9SMatt Spinler // Get the size using the repo attributes 251f77debb9SMatt Spinler Repository::LogID i{Repository::LogID::Pel{id}}; 252f77debb9SMatt Spinler if (auto attributes = _repo.getPELAttributes(i); attributes) 253f77debb9SMatt Spinler { 254f77debb9SMatt Spinler auto size = static_cast<size_t>( 255f77debb9SMatt Spinler std::filesystem::file_size((*attributes).get().path)); 256f77debb9SMatt Spinler auto rc = _hostIface->sendNewLogCmd(id, size); 257f77debb9SMatt Spinler 258f77debb9SMatt Spinler if (rc == CmdStatus::success) 259f77debb9SMatt Spinler { 260f77debb9SMatt Spinler _inProgressPEL = id; 261f77debb9SMatt Spinler } 262f77debb9SMatt Spinler else 263f77debb9SMatt Spinler { 264f77debb9SMatt Spinler // It failed. Retry 265f77debb9SMatt Spinler log<level::ERR>("PLDM send failed", entry("PEL_ID=0x%X", id)); 266f77debb9SMatt Spinler _pelQueue.push_front(id); 267f77debb9SMatt Spinler _inProgressPEL = 0; 268f77debb9SMatt Spinler _retryTimer.restartOnce(_hostIface->getSendRetryDelay()); 269f77debb9SMatt Spinler } 270f77debb9SMatt Spinler } 271f77debb9SMatt Spinler else 272f77debb9SMatt Spinler { 273f77debb9SMatt Spinler log<level::ERR>("PEL ID not in repository. Cannot notify host", 274f77debb9SMatt Spinler entry("PEL_ID=0x%X", id)); 275f77debb9SMatt Spinler } 276f77debb9SMatt Spinler } 277f60ac27eSMatt Spinler } 278f60ac27eSMatt Spinler 279f60ac27eSMatt Spinler void HostNotifier::hostStateChange(bool hostUp) 280f60ac27eSMatt Spinler { 2813019c6fbSMatt Spinler _retryCount = 0; 28241293cb8SMatt Spinler _hostFull = false; 2833019c6fbSMatt Spinler 2843019c6fbSMatt Spinler if (hostUp && !_pelQueue.empty()) 2853019c6fbSMatt Spinler { 2863019c6fbSMatt Spinler doNewLogNotify(); 2873019c6fbSMatt Spinler } 2883019c6fbSMatt Spinler else if (!hostUp) 2893019c6fbSMatt Spinler { 2903019c6fbSMatt Spinler stopCommand(); 2913019c6fbSMatt Spinler 2923019c6fbSMatt Spinler // Reset the state on any PELs that were sent but not acked back 2933019c6fbSMatt Spinler // to new so they'll get sent again. 2943019c6fbSMatt Spinler for (auto id : _sentPELs) 2953019c6fbSMatt Spinler { 2963019c6fbSMatt Spinler _pelQueue.push_back(id); 2973019c6fbSMatt Spinler _repo.setPELHostTransState(id, TransmissionState::newPEL); 2983019c6fbSMatt Spinler } 2993019c6fbSMatt Spinler 3003019c6fbSMatt Spinler _sentPELs.clear(); 30141293cb8SMatt Spinler 30241293cb8SMatt Spinler if (_hostFullTimer.isEnabled()) 30341293cb8SMatt Spinler { 30441293cb8SMatt Spinler _hostFullTimer.setEnabled(false); 30541293cb8SMatt Spinler } 3063019c6fbSMatt Spinler } 307f60ac27eSMatt Spinler } 308f60ac27eSMatt Spinler 309f60ac27eSMatt Spinler void HostNotifier::commandResponse(ResponseStatus status) 310f60ac27eSMatt Spinler { 311f869fcf8SMatt Spinler auto id = _inProgressPEL; 312f869fcf8SMatt Spinler _inProgressPEL = 0; 313f869fcf8SMatt Spinler 314f869fcf8SMatt Spinler if (status == ResponseStatus::success) 315f869fcf8SMatt Spinler { 316f869fcf8SMatt Spinler _retryCount = 0; 317f869fcf8SMatt Spinler 318f869fcf8SMatt Spinler _sentPELs.push_back(id); 319f869fcf8SMatt Spinler 320f869fcf8SMatt Spinler _repo.setPELHostTransState(id, TransmissionState::sent); 321f869fcf8SMatt Spinler 32241293cb8SMatt Spinler // If the host is full, don't send off the next PEL 32341293cb8SMatt Spinler if (!_hostFull && !_pelQueue.empty()) 324f869fcf8SMatt Spinler { 325f869fcf8SMatt Spinler doNewLogNotify(); 326f869fcf8SMatt Spinler } 327f869fcf8SMatt Spinler } 328f869fcf8SMatt Spinler else 329f869fcf8SMatt Spinler { 330f869fcf8SMatt Spinler log<level::ERR>("PLDM command response failure", 331f869fcf8SMatt Spinler entry("PEL_ID=0x%X", id)); 332f869fcf8SMatt Spinler // Retry 333f869fcf8SMatt Spinler _pelQueue.push_front(id); 334f869fcf8SMatt Spinler _retryTimer.restartOnce(_hostIface->getReceiveRetryDelay()); 335f869fcf8SMatt Spinler } 336f869fcf8SMatt Spinler } 337f869fcf8SMatt Spinler 338f869fcf8SMatt Spinler void HostNotifier::retryTimerExpired() 339f869fcf8SMatt Spinler { 340f869fcf8SMatt Spinler if (_dataIface.isHostUp()) 341f869fcf8SMatt Spinler { 342f869fcf8SMatt Spinler log<level::INFO>("Attempting command retry", 343f869fcf8SMatt Spinler entry("PEL_ID=0x%X", _pelQueue.front())); 344f869fcf8SMatt Spinler _retryCount++; 345f869fcf8SMatt Spinler doNewLogNotify(); 346f869fcf8SMatt Spinler } 347f60ac27eSMatt Spinler } 348f60ac27eSMatt Spinler 34941293cb8SMatt Spinler void HostNotifier::hostFullTimerExpired() 35041293cb8SMatt Spinler { 35141293cb8SMatt Spinler doNewLogNotify(); 35241293cb8SMatt Spinler } 35341293cb8SMatt Spinler 3543019c6fbSMatt Spinler void HostNotifier::stopCommand() 3553019c6fbSMatt Spinler { 3563019c6fbSMatt Spinler _retryCount = 0; 3573019c6fbSMatt Spinler 3583019c6fbSMatt Spinler if (_inProgressPEL != 0) 3593019c6fbSMatt Spinler { 3603019c6fbSMatt Spinler _pelQueue.push_front(_inProgressPEL); 3613019c6fbSMatt Spinler _inProgressPEL = 0; 3623019c6fbSMatt Spinler } 3633019c6fbSMatt Spinler 3643019c6fbSMatt Spinler if (_retryTimer.isEnabled()) 3653019c6fbSMatt Spinler { 3663019c6fbSMatt Spinler _retryTimer.setEnabled(false); 3673019c6fbSMatt Spinler } 3683019c6fbSMatt Spinler 369*829b052dSMatt Spinler // Ensure the PLDM instance ID is released 3703019c6fbSMatt Spinler _hostIface->cancelCmd(); 3713019c6fbSMatt Spinler } 3723019c6fbSMatt Spinler 373cc3b64aeSMatt Spinler void HostNotifier::ackPEL(uint32_t id) 374cc3b64aeSMatt Spinler { 375cc3b64aeSMatt Spinler _repo.setPELHostTransState(id, TransmissionState::acked); 376cc3b64aeSMatt Spinler 377cc3b64aeSMatt Spinler // No longer just 'sent', so remove it from the sent list. 378cc3b64aeSMatt Spinler auto sent = std::find(_sentPELs.begin(), _sentPELs.end(), id); 379cc3b64aeSMatt Spinler if (sent != _sentPELs.end()) 380cc3b64aeSMatt Spinler { 381cc3b64aeSMatt Spinler _sentPELs.erase(sent); 382cc3b64aeSMatt Spinler } 38341293cb8SMatt Spinler 38441293cb8SMatt Spinler // An ack means the host is no longer full 38541293cb8SMatt Spinler if (_hostFullTimer.isEnabled()) 38641293cb8SMatt Spinler { 38741293cb8SMatt Spinler _hostFullTimer.setEnabled(false); 38841293cb8SMatt Spinler } 38941293cb8SMatt Spinler 39041293cb8SMatt Spinler if (_hostFull) 39141293cb8SMatt Spinler { 39241293cb8SMatt Spinler _hostFull = false; 39341293cb8SMatt Spinler 39441293cb8SMatt Spinler // Start sending PELs again, from the event loop 39541293cb8SMatt Spinler if (!_pelQueue.empty()) 39641293cb8SMatt Spinler { 39741293cb8SMatt Spinler scheduleDispatch(); 39841293cb8SMatt Spinler } 39941293cb8SMatt Spinler } 40041293cb8SMatt Spinler } 40141293cb8SMatt Spinler 40241293cb8SMatt Spinler void HostNotifier::setHostFull(uint32_t id) 40341293cb8SMatt Spinler { 40441293cb8SMatt Spinler log<level::INFO>("Received Host full indication", entry("PEL_ID=0x%X", id)); 40541293cb8SMatt Spinler 40641293cb8SMatt Spinler _hostFull = true; 40741293cb8SMatt Spinler 40841293cb8SMatt Spinler // This PEL needs to get re-sent 40941293cb8SMatt Spinler auto sent = std::find(_sentPELs.begin(), _sentPELs.end(), id); 41041293cb8SMatt Spinler if (sent != _sentPELs.end()) 41141293cb8SMatt Spinler { 41241293cb8SMatt Spinler _sentPELs.erase(sent); 41341293cb8SMatt Spinler _repo.setPELHostTransState(id, TransmissionState::newPEL); 41441293cb8SMatt Spinler 41541293cb8SMatt Spinler if (std::find(_pelQueue.begin(), _pelQueue.end(), id) == 41641293cb8SMatt Spinler _pelQueue.end()) 41741293cb8SMatt Spinler { 41841293cb8SMatt Spinler _pelQueue.push_front(id); 41941293cb8SMatt Spinler } 42041293cb8SMatt Spinler } 42141293cb8SMatt Spinler 42241293cb8SMatt Spinler // The only PELs that will be sent when the 42341293cb8SMatt Spinler // host is full is from this timer callback. 42441293cb8SMatt Spinler if (!_hostFullTimer.isEnabled()) 42541293cb8SMatt Spinler { 42641293cb8SMatt Spinler _hostFullTimer.restartOnce(_hostIface->getHostFullRetryDelay()); 42741293cb8SMatt Spinler } 428cc3b64aeSMatt Spinler } 429cc3b64aeSMatt Spinler 430a19b6234SMatt Spinler void HostNotifier::setBadPEL(uint32_t id) 431a19b6234SMatt Spinler { 432a19b6234SMatt Spinler log<level::ERR>("PEL rejected by the host", entry("PEL_ID=0x%X", id)); 433a19b6234SMatt Spinler 434a19b6234SMatt Spinler auto sent = std::find(_sentPELs.begin(), _sentPELs.end(), id); 435a19b6234SMatt Spinler if (sent != _sentPELs.end()) 436a19b6234SMatt Spinler { 437a19b6234SMatt Spinler _sentPELs.erase(sent); 438a19b6234SMatt Spinler } 439a19b6234SMatt Spinler 440a19b6234SMatt Spinler _repo.setPELHostTransState(id, TransmissionState::badPEL); 441a19b6234SMatt Spinler } 442a19b6234SMatt Spinler 443f60ac27eSMatt Spinler } // namespace openpower::pels 444