summaryrefslogtreecommitdiffstats
path: root/host-interface.cpp
diff options
context:
space:
mode:
authorVishwanatha Subbanna <vishwa@linux.vnet.ibm.com>2017-07-12 16:13:49 +0530
committerPatrick Williams <patrick@stwcx.xyz>2017-08-14 18:47:08 +0000
commit3eb117a322aca11f049bb05beea5eb2f6385cb8e (patch)
treef3352df962e284c1d239e38a57955c1fa8b6ddca /host-interface.cpp
parentac149a94543c9fae468cf45e47103998153c89a5 (diff)
downloadphosphor-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.cpp147
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
OpenPOWER on IntegriCloud