blob: 28bcb70debf0eef53adeb6e8391e8878581a4476 [file] [log] [blame]
Patrick Venture46470a32018-09-07 19:26:25 -07001#include "config.h"
2
3#include "host-cmd-manager.hpp"
4
5#include "systemintfcmds.hpp"
Patrick Venture0b02be92018-08-31 11:55:55 -07006
Vishwanatha Subbannaac149a92017-07-11 18:16:50 +05307#include <chrono>
Vishwanatha Subbannaac149a92017-07-11 18:16:50 +05308#include <phosphor-logging/elog-errors.hpp>
Patrick Venture0b02be92018-08-31 11:55:55 -07009#include <phosphor-logging/log.hpp>
William A. Kennington III4c008022018-10-12 17:18:14 -070010#include <sdbusplus/message/types.hpp>
Vernon Mauery1181af72018-10-08 12:05:00 -070011#include <sdbusplus/timer.hpp>
12#include <utils.hpp>
Vishwanatha Subbannaac149a92017-07-11 18:16:50 +053013#include <xyz/openbmc_project/Common/error.hpp>
Matt Spinler15309ef2018-06-27 13:01:25 -050014#include <xyz/openbmc_project/State/Host/server.hpp>
Vishwanatha Subbanna6e8979d2017-07-13 16:48:20 +053015
Vishwanatha Subbannaac149a92017-07-11 18:16:50 +053016namespace phosphor
17{
18namespace host
19{
20namespace command
21{
22
23constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
24constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper";
25constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper";
Matt Spinler15309ef2018-06-27 13:01:25 -050026constexpr auto HOST_STATE_PATH = "/xyz/openbmc_project/state/host0";
27constexpr auto HOST_STATE_INTERFACE = "xyz.openbmc_project.State.Host";
28constexpr auto HOST_TRANS_PROP = "RequestedHostTransition";
Vishwanatha Subbannaac149a92017-07-11 18:16:50 +053029
30// For throwing exceptions
31using namespace phosphor::logging;
Patrick Venture0b02be92018-08-31 11:55:55 -070032using InternalFailure =
33 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
Vishwanatha Subbannaac149a92017-07-11 18:16:50 +053034
Matt Spinler15309ef2018-06-27 13:01:25 -050035namespace sdbusRule = sdbusplus::bus::match::rules;
William A. Kennington III4c008022018-10-12 17:18:14 -070036namespace variant_ns = sdbusplus::message::variant_ns;
Matt Spinler15309ef2018-06-27 13:01:25 -050037
Vishwanatha Subbanna6e8979d2017-07-13 16:48:20 +053038Manager::Manager(sdbusplus::bus::bus& bus, sd_event* event) :
Patrick Venture0b02be92018-08-31 11:55:55 -070039 bus(bus), timer(event, std::bind(&Manager::hostTimeout, this)),
40 hostTransitionMatch(
41 bus,
42 sdbusRule::propertiesChanged(HOST_STATE_PATH, HOST_STATE_INTERFACE),
43 std::bind(&Manager::clearQueueOnPowerOn, this, std::placeholders::_1))
Vishwanatha Subbanna6e8979d2017-07-13 16:48:20 +053044{
45 // Nothing to do here.
46}
47
Vishwanatha Subbannaac149a92017-07-11 18:16:50 +053048// Called as part of READ_MSG_DATA command
49IpmiCmdData Manager::getNextCommand()
50{
51 // Stop the timer. Don't have to Err failure doing so.
Vernon Mauery1181af72018-10-08 12:05:00 -070052 auto r = timer.stop();
Vishwanatha Subbannaac149a92017-07-11 18:16:50 +053053 if (r < 0)
54 {
55 log<level::ERR>("Failure to STOP the timer",
Patrick Venture0b02be92018-08-31 11:55:55 -070056 entry("ERROR=%s", strerror(-r)));
Vishwanatha Subbannaac149a92017-07-11 18:16:50 +053057 }
58
Patrick Venture0b02be92018-08-31 11:55:55 -070059 if (this->workQueue.empty())
Vishwanatha Subbannaac149a92017-07-11 18:16:50 +053060 {
61 // Just return a heartbeat in this case. A spurious SMS_ATN was
62 // asserted for the host (probably from a previous boot).
Aditya Saripalli5fb14602017-11-09 14:46:27 +053063 log<level::DEBUG>("Control Host work queue is empty!");
Vishwanatha Subbannaac149a92017-07-11 18:16:50 +053064
65 return std::make_pair(CMD_HEARTBEAT, 0x00);
66 }
67
68 // Pop the processed entry off the queue
69 auto command = this->workQueue.front();
70 this->workQueue.pop();
71
72 // IPMI command is the first element in pair
73 auto ipmiCmdData = std::get<0>(command);
74
75 // Now, call the user registered functions so that
76 // implementation specific CommandComplete signals
77 // can be sent. `true` indicating Success.
78 std::get<CallBack>(command)(ipmiCmdData, true);
79
80 // Check for another entry in the queue and kick it off
81 this->checkQueueAndAlertHost();
82
83 // Tuple of command and data
84 return ipmiCmdData;
85}
86
87// Called when initial timer goes off post sending SMS_ATN
88void Manager::hostTimeout()
89{
90 log<level::ERR>("Host control timeout hit!");
91
Matt Spinler15309ef2018-06-27 13:01:25 -050092 clearQueue();
93}
94
95void Manager::clearQueue()
96{
Vishwanatha Subbannaac149a92017-07-11 18:16:50 +053097 // Dequeue all entries and send fail signal
Patrick Venture0b02be92018-08-31 11:55:55 -070098 while (!this->workQueue.empty())
Vishwanatha Subbannaac149a92017-07-11 18:16:50 +053099 {
100 auto command = this->workQueue.front();
101 this->workQueue.pop();
102
103 // IPMI command is the first element in pair
104 auto ipmiCmdData = std::get<0>(command);
105
106 // Call the implementation specific Command Failure.
107 // `false` indicating Failure
108 std::get<CallBack>(command)(ipmiCmdData, false);
109 }
110}
111
112// Called for alerting the host
113void Manager::checkQueueAndAlertHost()
114{
115 if (this->workQueue.size() >= 1)
116 {
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530117 log<level::DEBUG>("Asserting SMS Attention");
Vishwanatha Subbannaac149a92017-07-11 18:16:50 +0530118
119 std::string IPMI_PATH("/org/openbmc/HostIpmi/1");
120 std::string IPMI_INTERFACE("org.openbmc.HostIpmi");
121
Patrick Venture0b02be92018-08-31 11:55:55 -0700122 auto host = ::ipmi::getService(this->bus, IPMI_INTERFACE, IPMI_PATH);
Vishwanatha Subbannaac149a92017-07-11 18:16:50 +0530123
124 // Start the timer for this transaction
125 auto time = std::chrono::duration_cast<std::chrono::microseconds>(
Patrick Venture0b02be92018-08-31 11:55:55 -0700126 std::chrono::seconds(IPMI_SMS_ATN_ACK_TIMEOUT_SECS));
Vishwanatha Subbannaac149a92017-07-11 18:16:50 +0530127
Vernon Mauery1181af72018-10-08 12:05:00 -0700128 auto r = timer.start(time);
Vishwanatha Subbannaac149a92017-07-11 18:16:50 +0530129 if (r < 0)
130 {
131 log<level::ERR>("Error starting timer for control host");
132 return;
133 }
134
Patrick Venture0b02be92018-08-31 11:55:55 -0700135 auto method =
136 this->bus.new_method_call(host.c_str(), IPMI_PATH.c_str(),
137 IPMI_INTERFACE.c_str(), "setAttention");
Vishwanatha Subbannaac149a92017-07-11 18:16:50 +0530138 auto reply = this->bus.call(method);
139
140 if (reply.is_method_error())
141 {
142 log<level::ERR>("Error in setting SMS attention");
143 elog<InternalFailure>();
144 }
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530145 log<level::DEBUG>("SMS Attention asserted");
Vishwanatha Subbannaac149a92017-07-11 18:16:50 +0530146 }
147}
148
149// Called by specific implementations that provide commands
150void Manager::execute(CommandHandler command)
151{
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530152 log<level::DEBUG>("Pushing cmd on to queue",
Patrick Venture0b02be92018-08-31 11:55:55 -0700153 entry("COMMAND=%d", std::get<0>(command).first));
Vishwanatha Subbannaac149a92017-07-11 18:16:50 +0530154
155 this->workQueue.emplace(command);
156
157 // Alert host if this is only command in queue otherwise host will
158 // be notified of next message after processing the current one
159 if (this->workQueue.size() == 1)
160 {
161 this->checkQueueAndAlertHost();
162 }
163 else
164 {
165 log<level::INFO>("Command in process, no attention");
166 }
167
168 return;
169}
170
Matt Spinler15309ef2018-06-27 13:01:25 -0500171void Manager::clearQueueOnPowerOn(sdbusplus::message::message& msg)
172{
173 namespace server = sdbusplus::xyz::openbmc_project::State::server;
174
175 ::ipmi::DbusInterface interface;
176 ::ipmi::PropertyMap properties;
177
178 msg.read(interface, properties);
179
180 if (properties.find(HOST_TRANS_PROP) == properties.end())
181 {
182 return;
183 }
184
William A. Kennington III4c008022018-10-12 17:18:14 -0700185 auto& requestedState =
186 variant_ns::get<std::string>(properties.at(HOST_TRANS_PROP));
Matt Spinler15309ef2018-06-27 13:01:25 -0500187
188 if (server::Host::convertTransitionFromString(requestedState) ==
Patrick Venture0b02be92018-08-31 11:55:55 -0700189 server::Host::Transition::On)
Matt Spinler15309ef2018-06-27 13:01:25 -0500190 {
191 clearQueue();
192 }
193}
194
Vishwanatha Subbannaac149a92017-07-11 18:16:50 +0530195} // namespace command
196} // namespace host
Patrick Venture0b02be92018-08-31 11:55:55 -0700197} // namespace phosphor