From 8315970370d63b101bd0bd579bc1f697a3c8d07c Mon Sep 17 00:00:00 2001 From: Andrew Geissler Date: Mon, 3 Apr 2017 13:31:13 -0500 Subject: Add timeout support to host control On timeout, send error signal for all commands within the queue Change-Id: Ic995fd4b057bd83f121a3deec405a26e0991e9a2 Signed-off-by: Andrew Geissler --- host-interface.cpp | 58 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 5 deletions(-) (limited to 'host-interface.cpp') diff --git a/host-interface.cpp b/host-interface.cpp index 160c127..be2bd99 100644 --- a/host-interface.cpp +++ b/host-interface.cpp @@ -1,6 +1,9 @@ +#include #include #include +#include #include "host-interface.hpp" +#include "elog-errors.hpp" namespace phosphor { @@ -16,10 +19,45 @@ using namespace phosphor::logging; // When you see base:: you know we're referencing our base class namespace base = sdbusplus::xyz::openbmc_project::Control::server; -// TODO - Add timeout function? -// - If host does not respond to SMS, need to signal a failure -// - Flush queue on power off? - Timeout would do this for us for free -// - Ignore requests when host state not running? - Timeout handles too +base::Host::Command Host::getNextCommand() +{ + // Stop the timer + auto r = timer.setTimer(SD_EVENT_OFF); + if (r < 0) + { + log("Failure to STOP the timer", + entry("ERROR=%s", strerror(-r))); + } + + if(this->workQueue.empty()) + { + log("Control Host work queue is empty!"); + elog(); + } + + // Pop the processed entry off the queue + Command command = this->workQueue.front(); + this->workQueue.pop(); + + // Issue command complete signal + this->commandComplete(command, Result::Success); + + // Check for another entry in the queue and kick it off + this->checkQueue(); + return command; +} + +void Host::hostTimeout() +{ + log("Host control timeout hit!"); + // Dequeue all entries and send fail signal + while(!this->workQueue.empty()) + { + auto command = this->workQueue.front(); + this->workQueue.pop(); + this->commandComplete(command,Result::Failure); + } +} void Host::checkQueue() { @@ -30,7 +68,17 @@ void Host::checkQueue() std::string IPMI_PATH("/org/openbmc/HostIpmi/1"); std::string IPMI_INTERFACE("org.openbmc.HostIpmi"); - auto host = ipmi::getService(this->bus,IPMI_INTERFACE,IPMI_PATH); + auto host = ::ipmi::getService(this->bus,IPMI_INTERFACE,IPMI_PATH); + + // Start the timer for this transaction + auto time = std::chrono::duration_cast( + std::chrono::seconds(IPMI_SMS_ATN_ACK_TIMEOUT_SECS)); + auto r = timer.startTimer(time); + if (r < 0) + { + log("Error starting timer for control host"); + return; + } auto method = this->bus.new_method_call(host.c_str(), IPMI_PATH.c_str(), -- cgit v1.2.1