146470a38SPatrick Venture #include "config.h"
246470a38SPatrick Venture
346470a38SPatrick Venture #include "host-cmd-manager.hpp"
446470a38SPatrick Venture
546470a38SPatrick Venture #include "systemintfcmds.hpp"
60b02be92SPatrick Venture
76a98fe7fSVernon Mauery #include <ipmid/utils.hpp>
8ac149a94SVishwanatha Subbanna #include <phosphor-logging/elog-errors.hpp>
9*59d6dbb6SGeorge Liu #include <phosphor-logging/lg2.hpp>
104c008028SWilliam A. Kennington III #include <sdbusplus/message/types.hpp>
111181af74SVernon Mauery #include <sdbusplus/timer.hpp>
12ac149a94SVishwanatha Subbanna #include <xyz/openbmc_project/Common/error.hpp>
1315309efcSMatt Spinler #include <xyz/openbmc_project/State/Host/server.hpp>
146e8979d2SVishwanatha Subbanna
15fbc6c9d7SPatrick Williams #include <chrono>
16fbc6c9d7SPatrick Williams
17ac149a94SVishwanatha Subbanna namespace phosphor
18ac149a94SVishwanatha Subbanna {
19ac149a94SVishwanatha Subbanna namespace host
20ac149a94SVishwanatha Subbanna {
21ac149a94SVishwanatha Subbanna namespace command
22ac149a94SVishwanatha Subbanna {
23ac149a94SVishwanatha Subbanna
2415309efcSMatt Spinler constexpr auto HOST_STATE_PATH = "/xyz/openbmc_project/state/host0";
2515309efcSMatt Spinler constexpr auto HOST_STATE_INTERFACE = "xyz.openbmc_project.State.Host";
2615309efcSMatt Spinler constexpr auto HOST_TRANS_PROP = "RequestedHostTransition";
27ac149a94SVishwanatha Subbanna
28ac149a94SVishwanatha Subbanna // For throwing exceptions
29ac149a94SVishwanatha Subbanna using namespace phosphor::logging;
300b02be92SPatrick Venture using InternalFailure =
31523e2d1bSWilly Tu sdbusplus::error::xyz::openbmc_project::common::InternalFailure;
32ac149a94SVishwanatha Subbanna
3315309efcSMatt Spinler namespace sdbusRule = sdbusplus::bus::match::rules;
3415309efcSMatt Spinler
Manager(sdbusplus::bus_t & bus)355d82f474SPatrick Williams Manager::Manager(sdbusplus::bus_t& bus) :
36316f23d9SVernon Mauery bus(bus), timer(std::bind(&Manager::hostTimeout, this)),
370b02be92SPatrick Venture hostTransitionMatch(
380b02be92SPatrick Venture bus,
390b02be92SPatrick Venture sdbusRule::propertiesChanged(HOST_STATE_PATH, HOST_STATE_INTERFACE),
400b02be92SPatrick Venture std::bind(&Manager::clearQueueOnPowerOn, this, std::placeholders::_1))
416e8979d2SVishwanatha Subbanna {
426e8979d2SVishwanatha Subbanna // Nothing to do here.
436e8979d2SVishwanatha Subbanna }
446e8979d2SVishwanatha Subbanna
45ac149a94SVishwanatha Subbanna // Called as part of READ_MSG_DATA command
getNextCommand()46ac149a94SVishwanatha Subbanna IpmiCmdData Manager::getNextCommand()
47ac149a94SVishwanatha Subbanna {
48ac149a94SVishwanatha Subbanna // Stop the timer. Don't have to Err failure doing so.
491181af74SVernon Mauery auto r = timer.stop();
50ac149a94SVishwanatha Subbanna if (r < 0)
51ac149a94SVishwanatha Subbanna {
52*59d6dbb6SGeorge Liu lg2::error("Failure to STOP the timer: {ERROR}", "ERROR", strerror(-r));
53ac149a94SVishwanatha Subbanna }
54ac149a94SVishwanatha Subbanna
55ac149a94SVishwanatha Subbanna if (this->workQueue.empty())
56ac149a94SVishwanatha Subbanna {
57ac149a94SVishwanatha Subbanna // Just return a heartbeat in this case. A spurious SMS_ATN was
58ac149a94SVishwanatha Subbanna // asserted for the host (probably from a previous boot).
59*59d6dbb6SGeorge Liu lg2::debug("Control Host work queue is empty!");
60ac149a94SVishwanatha Subbanna
61ac149a94SVishwanatha Subbanna return std::make_pair(CMD_HEARTBEAT, 0x00);
62ac149a94SVishwanatha Subbanna }
63ac149a94SVishwanatha Subbanna
64ac149a94SVishwanatha Subbanna // Pop the processed entry off the queue
65ac149a94SVishwanatha Subbanna auto command = this->workQueue.front();
66ac149a94SVishwanatha Subbanna this->workQueue.pop();
67ac149a94SVishwanatha Subbanna
68ac149a94SVishwanatha Subbanna // IPMI command is the first element in pair
69ac149a94SVishwanatha Subbanna auto ipmiCmdData = std::get<0>(command);
70ac149a94SVishwanatha Subbanna
71ac149a94SVishwanatha Subbanna // Now, call the user registered functions so that
72ac149a94SVishwanatha Subbanna // implementation specific CommandComplete signals
73ac149a94SVishwanatha Subbanna // can be sent. `true` indicating Success.
74ac149a94SVishwanatha Subbanna std::get<CallBack>(command)(ipmiCmdData, true);
75ac149a94SVishwanatha Subbanna
76ac149a94SVishwanatha Subbanna // Check for another entry in the queue and kick it off
77ac149a94SVishwanatha Subbanna this->checkQueueAndAlertHost();
78ac149a94SVishwanatha Subbanna
79ac149a94SVishwanatha Subbanna // Tuple of command and data
80ac149a94SVishwanatha Subbanna return ipmiCmdData;
81ac149a94SVishwanatha Subbanna }
82ac149a94SVishwanatha Subbanna
83ac149a94SVishwanatha Subbanna // Called when initial timer goes off post sending SMS_ATN
hostTimeout()84ac149a94SVishwanatha Subbanna void Manager::hostTimeout()
85ac149a94SVishwanatha Subbanna {
86*59d6dbb6SGeorge Liu lg2::error("Host control timeout hit!");
87ac149a94SVishwanatha Subbanna
8815309efcSMatt Spinler clearQueue();
8915309efcSMatt Spinler }
9015309efcSMatt Spinler
clearQueue()9115309efcSMatt Spinler void Manager::clearQueue()
9215309efcSMatt Spinler {
93ac149a94SVishwanatha Subbanna // Dequeue all entries and send fail signal
94ac149a94SVishwanatha Subbanna while (!this->workQueue.empty())
95ac149a94SVishwanatha Subbanna {
96ac149a94SVishwanatha Subbanna auto command = this->workQueue.front();
97ac149a94SVishwanatha Subbanna this->workQueue.pop();
98ac149a94SVishwanatha Subbanna
99ac149a94SVishwanatha Subbanna // IPMI command is the first element in pair
100ac149a94SVishwanatha Subbanna auto ipmiCmdData = std::get<0>(command);
101ac149a94SVishwanatha Subbanna
102ac149a94SVishwanatha Subbanna // Call the implementation specific Command Failure.
103ac149a94SVishwanatha Subbanna // `false` indicating Failure
104ac149a94SVishwanatha Subbanna std::get<CallBack>(command)(ipmiCmdData, false);
105ac149a94SVishwanatha Subbanna }
106ac149a94SVishwanatha Subbanna }
107ac149a94SVishwanatha Subbanna
108ac149a94SVishwanatha Subbanna // Called for alerting the host
checkQueueAndAlertHost()109ac149a94SVishwanatha Subbanna void Manager::checkQueueAndAlertHost()
110ac149a94SVishwanatha Subbanna {
111ac149a94SVishwanatha Subbanna if (this->workQueue.size() >= 1)
112ac149a94SVishwanatha Subbanna {
113*59d6dbb6SGeorge Liu lg2::debug("Asserting SMS Attention");
114ac149a94SVishwanatha Subbanna
115b18c8bc3SAndrew Geissler std::string HOST_IPMI_SVC("org.openbmc.HostIpmi");
116ac149a94SVishwanatha Subbanna std::string IPMI_PATH("/org/openbmc/HostIpmi/1");
117ac149a94SVishwanatha Subbanna std::string IPMI_INTERFACE("org.openbmc.HostIpmi");
118ac149a94SVishwanatha Subbanna
119ac149a94SVishwanatha Subbanna // Start the timer for this transaction
120ac149a94SVishwanatha Subbanna auto time = std::chrono::duration_cast<std::chrono::microseconds>(
121ac149a94SVishwanatha Subbanna std::chrono::seconds(IPMI_SMS_ATN_ACK_TIMEOUT_SECS));
122ac149a94SVishwanatha Subbanna
1231181af74SVernon Mauery auto r = timer.start(time);
124ac149a94SVishwanatha Subbanna if (r < 0)
125ac149a94SVishwanatha Subbanna {
126*59d6dbb6SGeorge Liu lg2::error("Error starting timer for control host");
127ac149a94SVishwanatha Subbanna return;
128ac149a94SVishwanatha Subbanna }
129ac149a94SVishwanatha Subbanna
1300b02be92SPatrick Venture auto method =
131b18c8bc3SAndrew Geissler this->bus.new_method_call(HOST_IPMI_SVC.c_str(), IPMI_PATH.c_str(),
1320b02be92SPatrick Venture IPMI_INTERFACE.c_str(), "setAttention");
133897ae72fSThang Tran
134897ae72fSThang Tran try
135897ae72fSThang Tran {
136ac149a94SVishwanatha Subbanna auto reply = this->bus.call(method);
137ac149a94SVishwanatha Subbanna
138*59d6dbb6SGeorge Liu lg2::debug("SMS Attention asserted");
139ac149a94SVishwanatha Subbanna }
1405d82f474SPatrick Williams catch (sdbusplus::exception_t& e)
141897ae72fSThang Tran {
142*59d6dbb6SGeorge Liu lg2::error("Error when call setAttention method");
143897ae72fSThang Tran }
144897ae72fSThang Tran }
145ac149a94SVishwanatha Subbanna }
146ac149a94SVishwanatha Subbanna
147ac149a94SVishwanatha Subbanna // Called by specific implementations that provide commands
execute(CommandHandler command)148ac149a94SVishwanatha Subbanna void Manager::execute(CommandHandler command)
149ac149a94SVishwanatha Subbanna {
150*59d6dbb6SGeorge Liu lg2::debug("Pushing cmd on to queue, command: {COMMAND}", "COMMAND",
151*59d6dbb6SGeorge Liu std::get<0>(command).first);
152ac149a94SVishwanatha Subbanna
153ac149a94SVishwanatha Subbanna this->workQueue.emplace(command);
154ac149a94SVishwanatha Subbanna
155ac149a94SVishwanatha Subbanna // Alert host if this is only command in queue otherwise host will
156ac149a94SVishwanatha Subbanna // be notified of next message after processing the current one
157ac149a94SVishwanatha Subbanna if (this->workQueue.size() == 1)
158ac149a94SVishwanatha Subbanna {
159ac149a94SVishwanatha Subbanna this->checkQueueAndAlertHost();
160ac149a94SVishwanatha Subbanna }
161ac149a94SVishwanatha Subbanna else
162ac149a94SVishwanatha Subbanna {
163*59d6dbb6SGeorge Liu lg2::info("Command in process, no attention");
164ac149a94SVishwanatha Subbanna }
165ac149a94SVishwanatha Subbanna
166ac149a94SVishwanatha Subbanna return;
167ac149a94SVishwanatha Subbanna }
168ac149a94SVishwanatha Subbanna
clearQueueOnPowerOn(sdbusplus::message_t & msg)1695d82f474SPatrick Williams void Manager::clearQueueOnPowerOn(sdbusplus::message_t& msg)
17015309efcSMatt Spinler {
171523e2d1bSWilly Tu namespace server = sdbusplus::server::xyz::openbmc_project::state;
17215309efcSMatt Spinler
17315309efcSMatt Spinler ::ipmi::DbusInterface interface;
17415309efcSMatt Spinler ::ipmi::PropertyMap properties;
17515309efcSMatt Spinler
17615309efcSMatt Spinler msg.read(interface, properties);
17715309efcSMatt Spinler
17815309efcSMatt Spinler if (properties.find(HOST_TRANS_PROP) == properties.end())
17915309efcSMatt Spinler {
18015309efcSMatt Spinler return;
18115309efcSMatt Spinler }
18215309efcSMatt Spinler
1834c008028SWilliam A. Kennington III auto& requestedState =
184f442e119SVernon Mauery std::get<std::string>(properties.at(HOST_TRANS_PROP));
18515309efcSMatt Spinler
18615309efcSMatt Spinler if (server::Host::convertTransitionFromString(requestedState) ==
18715309efcSMatt Spinler server::Host::Transition::On)
18815309efcSMatt Spinler {
18915309efcSMatt Spinler clearQueue();
19015309efcSMatt Spinler }
19115309efcSMatt Spinler }
19215309efcSMatt Spinler
193ac149a94SVishwanatha Subbanna } // namespace command
194ac149a94SVishwanatha Subbanna } // namespace host
1950b02be92SPatrick Venture } // namespace phosphor
196