146470a38SPatrick Venture #include "config.h" 246470a38SPatrick Venture 346470a38SPatrick Venture #include "host-cmd-manager.hpp" 446470a38SPatrick Venture 546470a38SPatrick Venture #include "systemintfcmds.hpp" 60b02be92SPatrick Venture 7ac149a94SVishwanatha Subbanna #include <chrono> 8*6a98fe7fSVernon Mauery #include <ipmid/utils.hpp> 9ac149a94SVishwanatha Subbanna #include <phosphor-logging/elog-errors.hpp> 100b02be92SPatrick Venture #include <phosphor-logging/log.hpp> 114c008028SWilliam A. Kennington III #include <sdbusplus/message/types.hpp> 121181af74SVernon Mauery #include <sdbusplus/timer.hpp> 13ac149a94SVishwanatha Subbanna #include <xyz/openbmc_project/Common/error.hpp> 1415309efcSMatt Spinler #include <xyz/openbmc_project/State/Host/server.hpp> 156e8979d2SVishwanatha Subbanna 16ac149a94SVishwanatha Subbanna namespace phosphor 17ac149a94SVishwanatha Subbanna { 18ac149a94SVishwanatha Subbanna namespace host 19ac149a94SVishwanatha Subbanna { 20ac149a94SVishwanatha Subbanna namespace command 21ac149a94SVishwanatha Subbanna { 22ac149a94SVishwanatha Subbanna 23ac149a94SVishwanatha Subbanna constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper"; 24ac149a94SVishwanatha Subbanna constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper"; 25ac149a94SVishwanatha Subbanna constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper"; 2615309efcSMatt Spinler constexpr auto HOST_STATE_PATH = "/xyz/openbmc_project/state/host0"; 2715309efcSMatt Spinler constexpr auto HOST_STATE_INTERFACE = "xyz.openbmc_project.State.Host"; 2815309efcSMatt Spinler constexpr auto HOST_TRANS_PROP = "RequestedHostTransition"; 29ac149a94SVishwanatha Subbanna 30ac149a94SVishwanatha Subbanna // For throwing exceptions 31ac149a94SVishwanatha Subbanna using namespace phosphor::logging; 320b02be92SPatrick Venture using InternalFailure = 330b02be92SPatrick Venture sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 34ac149a94SVishwanatha Subbanna 3515309efcSMatt Spinler namespace sdbusRule = sdbusplus::bus::match::rules; 364c008028SWilliam A. Kennington III namespace variant_ns = sdbusplus::message::variant_ns; 3715309efcSMatt Spinler 38316f23d9SVernon Mauery Manager::Manager(sdbusplus::bus::bus& bus) : 39316f23d9SVernon Mauery bus(bus), timer(std::bind(&Manager::hostTimeout, this)), 400b02be92SPatrick Venture hostTransitionMatch( 410b02be92SPatrick Venture bus, 420b02be92SPatrick Venture sdbusRule::propertiesChanged(HOST_STATE_PATH, HOST_STATE_INTERFACE), 430b02be92SPatrick Venture std::bind(&Manager::clearQueueOnPowerOn, this, std::placeholders::_1)) 446e8979d2SVishwanatha Subbanna { 456e8979d2SVishwanatha Subbanna // Nothing to do here. 466e8979d2SVishwanatha Subbanna } 476e8979d2SVishwanatha Subbanna 48ac149a94SVishwanatha Subbanna // Called as part of READ_MSG_DATA command 49ac149a94SVishwanatha Subbanna IpmiCmdData Manager::getNextCommand() 50ac149a94SVishwanatha Subbanna { 51ac149a94SVishwanatha Subbanna // Stop the timer. Don't have to Err failure doing so. 521181af74SVernon Mauery auto r = timer.stop(); 53ac149a94SVishwanatha Subbanna if (r < 0) 54ac149a94SVishwanatha Subbanna { 55ac149a94SVishwanatha Subbanna log<level::ERR>("Failure to STOP the timer", 56ac149a94SVishwanatha Subbanna entry("ERROR=%s", strerror(-r))); 57ac149a94SVishwanatha Subbanna } 58ac149a94SVishwanatha Subbanna 59ac149a94SVishwanatha Subbanna if (this->workQueue.empty()) 60ac149a94SVishwanatha Subbanna { 61ac149a94SVishwanatha Subbanna // Just return a heartbeat in this case. A spurious SMS_ATN was 62ac149a94SVishwanatha Subbanna // asserted for the host (probably from a previous boot). 635fb14603SAditya Saripalli log<level::DEBUG>("Control Host work queue is empty!"); 64ac149a94SVishwanatha Subbanna 65ac149a94SVishwanatha Subbanna return std::make_pair(CMD_HEARTBEAT, 0x00); 66ac149a94SVishwanatha Subbanna } 67ac149a94SVishwanatha Subbanna 68ac149a94SVishwanatha Subbanna // Pop the processed entry off the queue 69ac149a94SVishwanatha Subbanna auto command = this->workQueue.front(); 70ac149a94SVishwanatha Subbanna this->workQueue.pop(); 71ac149a94SVishwanatha Subbanna 72ac149a94SVishwanatha Subbanna // IPMI command is the first element in pair 73ac149a94SVishwanatha Subbanna auto ipmiCmdData = std::get<0>(command); 74ac149a94SVishwanatha Subbanna 75ac149a94SVishwanatha Subbanna // Now, call the user registered functions so that 76ac149a94SVishwanatha Subbanna // implementation specific CommandComplete signals 77ac149a94SVishwanatha Subbanna // can be sent. `true` indicating Success. 78ac149a94SVishwanatha Subbanna std::get<CallBack>(command)(ipmiCmdData, true); 79ac149a94SVishwanatha Subbanna 80ac149a94SVishwanatha Subbanna // Check for another entry in the queue and kick it off 81ac149a94SVishwanatha Subbanna this->checkQueueAndAlertHost(); 82ac149a94SVishwanatha Subbanna 83ac149a94SVishwanatha Subbanna // Tuple of command and data 84ac149a94SVishwanatha Subbanna return ipmiCmdData; 85ac149a94SVishwanatha Subbanna } 86ac149a94SVishwanatha Subbanna 87ac149a94SVishwanatha Subbanna // Called when initial timer goes off post sending SMS_ATN 88ac149a94SVishwanatha Subbanna void Manager::hostTimeout() 89ac149a94SVishwanatha Subbanna { 90ac149a94SVishwanatha Subbanna log<level::ERR>("Host control timeout hit!"); 91ac149a94SVishwanatha Subbanna 9215309efcSMatt Spinler clearQueue(); 9315309efcSMatt Spinler } 9415309efcSMatt Spinler 9515309efcSMatt Spinler void Manager::clearQueue() 9615309efcSMatt Spinler { 97ac149a94SVishwanatha Subbanna // Dequeue all entries and send fail signal 98ac149a94SVishwanatha Subbanna while (!this->workQueue.empty()) 99ac149a94SVishwanatha Subbanna { 100ac149a94SVishwanatha Subbanna auto command = this->workQueue.front(); 101ac149a94SVishwanatha Subbanna this->workQueue.pop(); 102ac149a94SVishwanatha Subbanna 103ac149a94SVishwanatha Subbanna // IPMI command is the first element in pair 104ac149a94SVishwanatha Subbanna auto ipmiCmdData = std::get<0>(command); 105ac149a94SVishwanatha Subbanna 106ac149a94SVishwanatha Subbanna // Call the implementation specific Command Failure. 107ac149a94SVishwanatha Subbanna // `false` indicating Failure 108ac149a94SVishwanatha Subbanna std::get<CallBack>(command)(ipmiCmdData, false); 109ac149a94SVishwanatha Subbanna } 110ac149a94SVishwanatha Subbanna } 111ac149a94SVishwanatha Subbanna 112ac149a94SVishwanatha Subbanna // Called for alerting the host 113ac149a94SVishwanatha Subbanna void Manager::checkQueueAndAlertHost() 114ac149a94SVishwanatha Subbanna { 115ac149a94SVishwanatha Subbanna if (this->workQueue.size() >= 1) 116ac149a94SVishwanatha Subbanna { 1175fb14603SAditya Saripalli log<level::DEBUG>("Asserting SMS Attention"); 118ac149a94SVishwanatha Subbanna 119ac149a94SVishwanatha Subbanna std::string IPMI_PATH("/org/openbmc/HostIpmi/1"); 120ac149a94SVishwanatha Subbanna std::string IPMI_INTERFACE("org.openbmc.HostIpmi"); 121ac149a94SVishwanatha Subbanna 122ac149a94SVishwanatha Subbanna auto host = ::ipmi::getService(this->bus, IPMI_INTERFACE, IPMI_PATH); 123ac149a94SVishwanatha Subbanna 124ac149a94SVishwanatha Subbanna // Start the timer for this transaction 125ac149a94SVishwanatha Subbanna auto time = std::chrono::duration_cast<std::chrono::microseconds>( 126ac149a94SVishwanatha Subbanna std::chrono::seconds(IPMI_SMS_ATN_ACK_TIMEOUT_SECS)); 127ac149a94SVishwanatha Subbanna 1281181af74SVernon Mauery auto r = timer.start(time); 129ac149a94SVishwanatha Subbanna if (r < 0) 130ac149a94SVishwanatha Subbanna { 131ac149a94SVishwanatha Subbanna log<level::ERR>("Error starting timer for control host"); 132ac149a94SVishwanatha Subbanna return; 133ac149a94SVishwanatha Subbanna } 134ac149a94SVishwanatha Subbanna 1350b02be92SPatrick Venture auto method = 1360b02be92SPatrick Venture this->bus.new_method_call(host.c_str(), IPMI_PATH.c_str(), 1370b02be92SPatrick Venture IPMI_INTERFACE.c_str(), "setAttention"); 138ac149a94SVishwanatha Subbanna auto reply = this->bus.call(method); 139ac149a94SVishwanatha Subbanna 140ac149a94SVishwanatha Subbanna if (reply.is_method_error()) 141ac149a94SVishwanatha Subbanna { 142ac149a94SVishwanatha Subbanna log<level::ERR>("Error in setting SMS attention"); 143ac149a94SVishwanatha Subbanna elog<InternalFailure>(); 144ac149a94SVishwanatha Subbanna } 1455fb14603SAditya Saripalli log<level::DEBUG>("SMS Attention asserted"); 146ac149a94SVishwanatha Subbanna } 147ac149a94SVishwanatha Subbanna } 148ac149a94SVishwanatha Subbanna 149ac149a94SVishwanatha Subbanna // Called by specific implementations that provide commands 150ac149a94SVishwanatha Subbanna void Manager::execute(CommandHandler command) 151ac149a94SVishwanatha Subbanna { 1525fb14603SAditya Saripalli log<level::DEBUG>("Pushing cmd on to queue", 153ac149a94SVishwanatha Subbanna entry("COMMAND=%d", std::get<0>(command).first)); 154ac149a94SVishwanatha Subbanna 155ac149a94SVishwanatha Subbanna this->workQueue.emplace(command); 156ac149a94SVishwanatha Subbanna 157ac149a94SVishwanatha Subbanna // Alert host if this is only command in queue otherwise host will 158ac149a94SVishwanatha Subbanna // be notified of next message after processing the current one 159ac149a94SVishwanatha Subbanna if (this->workQueue.size() == 1) 160ac149a94SVishwanatha Subbanna { 161ac149a94SVishwanatha Subbanna this->checkQueueAndAlertHost(); 162ac149a94SVishwanatha Subbanna } 163ac149a94SVishwanatha Subbanna else 164ac149a94SVishwanatha Subbanna { 165ac149a94SVishwanatha Subbanna log<level::INFO>("Command in process, no attention"); 166ac149a94SVishwanatha Subbanna } 167ac149a94SVishwanatha Subbanna 168ac149a94SVishwanatha Subbanna return; 169ac149a94SVishwanatha Subbanna } 170ac149a94SVishwanatha Subbanna 17115309efcSMatt Spinler void Manager::clearQueueOnPowerOn(sdbusplus::message::message& msg) 17215309efcSMatt Spinler { 17315309efcSMatt Spinler namespace server = sdbusplus::xyz::openbmc_project::State::server; 17415309efcSMatt Spinler 17515309efcSMatt Spinler ::ipmi::DbusInterface interface; 17615309efcSMatt Spinler ::ipmi::PropertyMap properties; 17715309efcSMatt Spinler 17815309efcSMatt Spinler msg.read(interface, properties); 17915309efcSMatt Spinler 18015309efcSMatt Spinler if (properties.find(HOST_TRANS_PROP) == properties.end()) 18115309efcSMatt Spinler { 18215309efcSMatt Spinler return; 18315309efcSMatt Spinler } 18415309efcSMatt Spinler 1854c008028SWilliam A. Kennington III auto& requestedState = 1864c008028SWilliam A. Kennington III variant_ns::get<std::string>(properties.at(HOST_TRANS_PROP)); 18715309efcSMatt Spinler 18815309efcSMatt Spinler if (server::Host::convertTransitionFromString(requestedState) == 18915309efcSMatt Spinler server::Host::Transition::On) 19015309efcSMatt Spinler { 19115309efcSMatt Spinler clearQueue(); 19215309efcSMatt Spinler } 19315309efcSMatt Spinler } 19415309efcSMatt Spinler 195ac149a94SVishwanatha Subbanna } // namespace command 196ac149a94SVishwanatha Subbanna } // namespace host 1970b02be92SPatrick Venture } // namespace phosphor 198