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>
90b02be92SPatrick Venture #include <phosphor-logging/log.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 =
31*523e2d1bSWilly 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 {
52ac149a94SVishwanatha Subbanna log<level::ERR>("Failure to STOP the timer",
53ac149a94SVishwanatha Subbanna entry("ERROR=%s", strerror(-r)));
54ac149a94SVishwanatha Subbanna }
55ac149a94SVishwanatha Subbanna
56ac149a94SVishwanatha Subbanna if (this->workQueue.empty())
57ac149a94SVishwanatha Subbanna {
58ac149a94SVishwanatha Subbanna // Just return a heartbeat in this case. A spurious SMS_ATN was
59ac149a94SVishwanatha Subbanna // asserted for the host (probably from a previous boot).
605fb14603SAditya Saripalli log<level::DEBUG>("Control Host work queue is empty!");
61ac149a94SVishwanatha Subbanna
62ac149a94SVishwanatha Subbanna return std::make_pair(CMD_HEARTBEAT, 0x00);
63ac149a94SVishwanatha Subbanna }
64ac149a94SVishwanatha Subbanna
65ac149a94SVishwanatha Subbanna // Pop the processed entry off the queue
66ac149a94SVishwanatha Subbanna auto command = this->workQueue.front();
67ac149a94SVishwanatha Subbanna this->workQueue.pop();
68ac149a94SVishwanatha Subbanna
69ac149a94SVishwanatha Subbanna // IPMI command is the first element in pair
70ac149a94SVishwanatha Subbanna auto ipmiCmdData = std::get<0>(command);
71ac149a94SVishwanatha Subbanna
72ac149a94SVishwanatha Subbanna // Now, call the user registered functions so that
73ac149a94SVishwanatha Subbanna // implementation specific CommandComplete signals
74ac149a94SVishwanatha Subbanna // can be sent. `true` indicating Success.
75ac149a94SVishwanatha Subbanna std::get<CallBack>(command)(ipmiCmdData, true);
76ac149a94SVishwanatha Subbanna
77ac149a94SVishwanatha Subbanna // Check for another entry in the queue and kick it off
78ac149a94SVishwanatha Subbanna this->checkQueueAndAlertHost();
79ac149a94SVishwanatha Subbanna
80ac149a94SVishwanatha Subbanna // Tuple of command and data
81ac149a94SVishwanatha Subbanna return ipmiCmdData;
82ac149a94SVishwanatha Subbanna }
83ac149a94SVishwanatha Subbanna
84ac149a94SVishwanatha Subbanna // Called when initial timer goes off post sending SMS_ATN
hostTimeout()85ac149a94SVishwanatha Subbanna void Manager::hostTimeout()
86ac149a94SVishwanatha Subbanna {
87ac149a94SVishwanatha Subbanna log<level::ERR>("Host control timeout hit!");
88ac149a94SVishwanatha Subbanna
8915309efcSMatt Spinler clearQueue();
9015309efcSMatt Spinler }
9115309efcSMatt Spinler
clearQueue()9215309efcSMatt Spinler void Manager::clearQueue()
9315309efcSMatt Spinler {
94ac149a94SVishwanatha Subbanna // Dequeue all entries and send fail signal
95ac149a94SVishwanatha Subbanna while (!this->workQueue.empty())
96ac149a94SVishwanatha Subbanna {
97ac149a94SVishwanatha Subbanna auto command = this->workQueue.front();
98ac149a94SVishwanatha Subbanna this->workQueue.pop();
99ac149a94SVishwanatha Subbanna
100ac149a94SVishwanatha Subbanna // IPMI command is the first element in pair
101ac149a94SVishwanatha Subbanna auto ipmiCmdData = std::get<0>(command);
102ac149a94SVishwanatha Subbanna
103ac149a94SVishwanatha Subbanna // Call the implementation specific Command Failure.
104ac149a94SVishwanatha Subbanna // `false` indicating Failure
105ac149a94SVishwanatha Subbanna std::get<CallBack>(command)(ipmiCmdData, false);
106ac149a94SVishwanatha Subbanna }
107ac149a94SVishwanatha Subbanna }
108ac149a94SVishwanatha Subbanna
109ac149a94SVishwanatha Subbanna // Called for alerting the host
checkQueueAndAlertHost()110ac149a94SVishwanatha Subbanna void Manager::checkQueueAndAlertHost()
111ac149a94SVishwanatha Subbanna {
112ac149a94SVishwanatha Subbanna if (this->workQueue.size() >= 1)
113ac149a94SVishwanatha Subbanna {
1145fb14603SAditya Saripalli log<level::DEBUG>("Asserting SMS Attention");
115ac149a94SVishwanatha Subbanna
116b18c8bc3SAndrew Geissler std::string HOST_IPMI_SVC("org.openbmc.HostIpmi");
117ac149a94SVishwanatha Subbanna std::string IPMI_PATH("/org/openbmc/HostIpmi/1");
118ac149a94SVishwanatha Subbanna std::string IPMI_INTERFACE("org.openbmc.HostIpmi");
119ac149a94SVishwanatha Subbanna
120ac149a94SVishwanatha Subbanna // Start the timer for this transaction
121ac149a94SVishwanatha Subbanna auto time = std::chrono::duration_cast<std::chrono::microseconds>(
122ac149a94SVishwanatha Subbanna std::chrono::seconds(IPMI_SMS_ATN_ACK_TIMEOUT_SECS));
123ac149a94SVishwanatha Subbanna
1241181af74SVernon Mauery auto r = timer.start(time);
125ac149a94SVishwanatha Subbanna if (r < 0)
126ac149a94SVishwanatha Subbanna {
127ac149a94SVishwanatha Subbanna log<level::ERR>("Error starting timer for control host");
128ac149a94SVishwanatha Subbanna return;
129ac149a94SVishwanatha Subbanna }
130ac149a94SVishwanatha Subbanna
1310b02be92SPatrick Venture auto method =
132b18c8bc3SAndrew Geissler this->bus.new_method_call(HOST_IPMI_SVC.c_str(), IPMI_PATH.c_str(),
1330b02be92SPatrick Venture IPMI_INTERFACE.c_str(), "setAttention");
134897ae72fSThang Tran
135897ae72fSThang Tran try
136897ae72fSThang Tran {
137ac149a94SVishwanatha Subbanna auto reply = this->bus.call(method);
138ac149a94SVishwanatha Subbanna
1395fb14603SAditya Saripalli log<level::DEBUG>("SMS Attention asserted");
140ac149a94SVishwanatha Subbanna }
1415d82f474SPatrick Williams catch (sdbusplus::exception_t& e)
142897ae72fSThang Tran {
143897ae72fSThang Tran log<level::ERR>("Error when call setAttention method");
144897ae72fSThang Tran }
145897ae72fSThang Tran }
146ac149a94SVishwanatha Subbanna }
147ac149a94SVishwanatha Subbanna
148ac149a94SVishwanatha Subbanna // Called by specific implementations that provide commands
execute(CommandHandler command)149ac149a94SVishwanatha Subbanna void Manager::execute(CommandHandler command)
150ac149a94SVishwanatha Subbanna {
1515fb14603SAditya Saripalli log<level::DEBUG>("Pushing cmd on to queue",
152ac149a94SVishwanatha Subbanna entry("COMMAND=%d", std::get<0>(command).first));
153ac149a94SVishwanatha Subbanna
154ac149a94SVishwanatha Subbanna this->workQueue.emplace(command);
155ac149a94SVishwanatha Subbanna
156ac149a94SVishwanatha Subbanna // Alert host if this is only command in queue otherwise host will
157ac149a94SVishwanatha Subbanna // be notified of next message after processing the current one
158ac149a94SVishwanatha Subbanna if (this->workQueue.size() == 1)
159ac149a94SVishwanatha Subbanna {
160ac149a94SVishwanatha Subbanna this->checkQueueAndAlertHost();
161ac149a94SVishwanatha Subbanna }
162ac149a94SVishwanatha Subbanna else
163ac149a94SVishwanatha Subbanna {
164ac149a94SVishwanatha Subbanna log<level::INFO>("Command in process, no attention");
165ac149a94SVishwanatha Subbanna }
166ac149a94SVishwanatha Subbanna
167ac149a94SVishwanatha Subbanna return;
168ac149a94SVishwanatha Subbanna }
169ac149a94SVishwanatha Subbanna
clearQueueOnPowerOn(sdbusplus::message_t & msg)1705d82f474SPatrick Williams void Manager::clearQueueOnPowerOn(sdbusplus::message_t& msg)
17115309efcSMatt Spinler {
172*523e2d1bSWilly Tu namespace server = sdbusplus::server::xyz::openbmc_project::state;
17315309efcSMatt Spinler
17415309efcSMatt Spinler ::ipmi::DbusInterface interface;
17515309efcSMatt Spinler ::ipmi::PropertyMap properties;
17615309efcSMatt Spinler
17715309efcSMatt Spinler msg.read(interface, properties);
17815309efcSMatt Spinler
17915309efcSMatt Spinler if (properties.find(HOST_TRANS_PROP) == properties.end())
18015309efcSMatt Spinler {
18115309efcSMatt Spinler return;
18215309efcSMatt Spinler }
18315309efcSMatt Spinler
1844c008028SWilliam A. Kennington III auto& requestedState =
185f442e119SVernon Mauery std::get<std::string>(properties.at(HOST_TRANS_PROP));
18615309efcSMatt Spinler
18715309efcSMatt Spinler if (server::Host::convertTransitionFromString(requestedState) ==
18815309efcSMatt Spinler server::Host::Transition::On)
18915309efcSMatt Spinler {
19015309efcSMatt Spinler clearQueue();
19115309efcSMatt Spinler }
19215309efcSMatt Spinler }
19315309efcSMatt Spinler
194ac149a94SVishwanatha Subbanna } // namespace command
195ac149a94SVishwanatha Subbanna } // namespace host
1960b02be92SPatrick Venture } // namespace phosphor
197