diff options
author | Vishwanatha Subbanna <vishwa@linux.vnet.ibm.com> | 2017-07-12 16:13:49 +0530 |
---|---|---|
committer | Patrick Williams <patrick@stwcx.xyz> | 2017-08-14 18:47:08 +0000 |
commit | 3eb117a322aca11f049bb05beea5eb2f6385cb8e (patch) | |
tree | f3352df962e284c1d239e38a57955c1fa8b6ddca /host-interface.cpp | |
parent | ac149a94543c9fae468cf45e47103998153c89a5 (diff) | |
download | phosphor-host-ipmid-3eb117a322aca11f049bb05beea5eb2f6385cb8e.tar.gz phosphor-host-ipmid-3eb117a322aca11f049bb05beea5eb2f6385cb8e.zip |
Use Host Command Manager in host interface implementation
Change-Id: Icefce510a3a0022bf0288fa99518459b732a2e04
Signed-off-by: Vishwanatha Subbanna <vishwa@linux.vnet.ibm.com>
Diffstat (limited to 'host-interface.cpp')
-rw-r--r-- | host-interface.cpp | 147 |
1 files changed, 53 insertions, 94 deletions
diff --git a/host-interface.cpp b/host-interface.cpp index 0bce888..1de2629 100644 --- a/host-interface.cpp +++ b/host-interface.cpp @@ -1,122 +1,81 @@ -#include <chrono> -#include <phosphor-logging/log.hpp> +#include <functional> +#include <systemintfcmds.h> +#include <ipmid-host-cmd.hpp> #include <utils.hpp> +#include <phosphor-logging/log.hpp> #include <config.h> -#include "host-interface.hpp" - +#include <host-interface.hpp> namespace phosphor { namespace host { +namespace command +{ -constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper"; -constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper"; -constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper"; - -using namespace phosphor::logging; +// When you see Base:: you know we're referencing our base class +namespace Base = sdbusplus::xyz::openbmc_project::Control::server; -// When you see base:: you know we're referencing our base class -namespace base = sdbusplus::xyz::openbmc_project::Control::server; +// IPMI OEM command. +// https://github.com/openbmc/openbmc/issues/2082 for handling +// Non-OEM commands that need to send SMS_ATN +using OEMCmd = uint8_t; -base::Host::Command Host::getNextCommand() -{ - // Stop the timer - auto r = timer.setTimer(SD_EVENT_OFF); - if (r < 0) +// Map of IPMI OEM command to its equivalent interface command. +// This is needed when invoking the callback handler to indicate +// the status of the executed command. +static const std::map<OEMCmd, Host::Command> intfCommand = { { - log<level::ERR>("Failure to STOP the timer", - entry("ERROR=%s", strerror(-r))); - } - - if(this->workQueue.empty()) + CMD_HEARTBEAT, + Base::Host::Command::Heartbeat + }, { - // Just return a heartbeat in this case. A spurious SMS_ATN was - // asserted for the host (probably from a previous boot). - log<level::INFO>("Control Host work queue is empty!"); - return (Command::Heartbeat); + CMD_POWER, + Base::Host::Command::SoftOff } +}; - // 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<level::ERR>("Host control timeout hit!"); - // Dequeue all entries and send fail signal - while(!this->workQueue.empty()) +// Map of Interface command to its corresponding IPMI OEM command. +// This is needed when pushing IPMI commands to command manager's +// queue. The same pair will be returned when IPMI asks us +// why a SMS_ATN was sent +static const std::map<Host::Command, IpmiCmdData> ipmiCommand = { { - auto command = this->workQueue.front(); - this->workQueue.pop(); - this->commandComplete(command,Result::Failure); - } -} - -void Host::checkQueue() -{ - if (this->workQueue.size() >= 1) + Base::Host::Command::Heartbeat, + std::make_pair(CMD_HEARTBEAT, 0x00) + }, { - log<level::INFO>("Asserting SMS Attention"); - - 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); - - // Start the timer for this transaction - auto time = std::chrono::duration_cast<std::chrono::microseconds>( - std::chrono::seconds(IPMI_SMS_ATN_ACK_TIMEOUT_SECS)); - auto r = timer.startTimer(time); - if (r < 0) - { - log<level::ERR>("Error starting timer for control host"); - return; - } - - auto method = this->bus.new_method_call(host.c_str(), - IPMI_PATH.c_str(), - IPMI_INTERFACE.c_str(), - "setAttention"); - auto reply = this->bus.call(method); - - if (reply.is_method_error()) - { - log<level::ERR>("Error in setting SMS attention"); - throw std::runtime_error("ERROR in call to setAttention"); - } - log<level::INFO>("SMS Attention asserted"); + Base::Host::Command::SoftOff, + std::make_pair(CMD_POWER, SOFT_OFF) } -} +}; -void Host::execute(base::Host::Command command) +// Called at user request +void Host::execute(Base::Host::Command command) { + using namespace phosphor::logging; + log<level::INFO>("Pushing cmd on to queue", entry("CONTROL_HOST_CMD=%s", convertForMessage(command))); - this->workQueue.push(command); + auto cmd = std::make_tuple(ipmiCommand.at(command), + std::bind(&Host::commandStatusHandler, + this, std::placeholders::_1, + std::placeholders::_2)); - // Alert host if this is only command in queue otherwise host will - // be notified of next message after processing the current one - if (this->workQueue.size() == 1) - { - this->checkQueue(); - } - else - { - log<level::INFO>("Command in process, no attention"); - } + return ipmid_send_cmd_to_host(std::move(cmd)); +} + +// Called into by Command Manager +void Host::commandStatusHandler(IpmiCmdData cmd, bool status) +{ + // Need to convert <cmd> to the equivalent one mentioned in spec + auto value = status ? Result::Success : Result::Failure; - return; + // Fire a signal + this->commandComplete(intfCommand.at(std::get<0>(cmd)), value); } +} // namespace command } // namespace host } // namepsace phosphor |