| Andrew Geissler | 8315970 | 2017-04-03 13:31:13 -0500 | [diff] [blame] | 1 | #include <chrono> | 
| Andrew Geissler | 1c1bd75 | 2017-03-20 21:17:04 -0500 | [diff] [blame] | 2 | #include <phosphor-logging/log.hpp> | 
| Andrew Geissler | 1b9d4e5 | 2017-03-21 15:04:05 -0500 | [diff] [blame] | 3 | #include <utils.hpp> | 
| Andrew Geissler | 8315970 | 2017-04-03 13:31:13 -0500 | [diff] [blame] | 4 | #include <config.h> | 
| Andrew Geissler | dd2c6fd | 2017-03-16 15:53:20 -0500 | [diff] [blame] | 5 | #include "host-interface.hpp" | 
|  | 6 |  | 
|  | 7 | namespace phosphor | 
|  | 8 | { | 
|  | 9 | namespace host | 
|  | 10 | { | 
|  | 11 |  | 
| Andrew Geissler | 1b9d4e5 | 2017-03-21 15:04:05 -0500 | [diff] [blame] | 12 | constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper"; | 
|  | 13 | constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper"; | 
|  | 14 | constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper"; | 
|  | 15 |  | 
| Andrew Geissler | 1c1bd75 | 2017-03-20 21:17:04 -0500 | [diff] [blame] | 16 | using namespace phosphor::logging; | 
|  | 17 |  | 
|  | 18 | // When you see base:: you know we're referencing our base class | 
|  | 19 | namespace base = sdbusplus::xyz::openbmc_project::Control::server; | 
|  | 20 |  | 
| Andrew Geissler | 8315970 | 2017-04-03 13:31:13 -0500 | [diff] [blame] | 21 | base::Host::Command Host::getNextCommand() | 
|  | 22 | { | 
|  | 23 | // Stop the timer | 
|  | 24 | auto r = timer.setTimer(SD_EVENT_OFF); | 
|  | 25 | if (r < 0) | 
|  | 26 | { | 
|  | 27 | log<level::ERR>("Failure to STOP the timer", | 
|  | 28 | entry("ERROR=%s", strerror(-r))); | 
|  | 29 | } | 
|  | 30 |  | 
|  | 31 | if(this->workQueue.empty()) | 
|  | 32 | { | 
| Andrew Geissler | 758c1ae | 2017-06-07 21:17:45 -0500 | [diff] [blame] | 33 | // Just return a heartbeat in this case.  A spurious SMS_ATN was | 
|  | 34 | // asserted for the host (probably from a previous boot). | 
|  | 35 | log<level::INFO>("Control Host work queue is empty!"); | 
|  | 36 | return (Command::Heartbeat); | 
| Andrew Geissler | 8315970 | 2017-04-03 13:31:13 -0500 | [diff] [blame] | 37 | } | 
|  | 38 |  | 
|  | 39 | // Pop the processed entry off the queue | 
|  | 40 | Command command = this->workQueue.front(); | 
|  | 41 | this->workQueue.pop(); | 
|  | 42 |  | 
|  | 43 | // Issue command complete signal | 
|  | 44 | this->commandComplete(command, Result::Success); | 
|  | 45 |  | 
|  | 46 | // Check for another entry in the queue and kick it off | 
|  | 47 | this->checkQueue(); | 
|  | 48 | return command; | 
|  | 49 | } | 
|  | 50 |  | 
|  | 51 | void Host::hostTimeout() | 
|  | 52 | { | 
|  | 53 | log<level::ERR>("Host control timeout hit!"); | 
|  | 54 | // Dequeue all entries and send fail signal | 
|  | 55 | while(!this->workQueue.empty()) | 
|  | 56 | { | 
|  | 57 | auto command = this->workQueue.front(); | 
|  | 58 | this->workQueue.pop(); | 
|  | 59 | this->commandComplete(command,Result::Failure); | 
|  | 60 | } | 
|  | 61 | } | 
| Andrew Geissler | 1b9d4e5 | 2017-03-21 15:04:05 -0500 | [diff] [blame] | 62 |  | 
| Andrew Geissler | 0c07c32 | 2017-03-22 14:02:30 -0500 | [diff] [blame] | 63 | void Host::checkQueue() | 
|  | 64 | { | 
|  | 65 | if (this->workQueue.size() >= 1) | 
| Andrew Geissler | 1b9d4e5 | 2017-03-21 15:04:05 -0500 | [diff] [blame] | 66 | { | 
|  | 67 | log<level::INFO>("Asserting SMS Attention"); | 
|  | 68 |  | 
|  | 69 | std::string IPMI_PATH("/org/openbmc/HostIpmi/1"); | 
|  | 70 | std::string IPMI_INTERFACE("org.openbmc.HostIpmi"); | 
|  | 71 |  | 
| Andrew Geissler | 8315970 | 2017-04-03 13:31:13 -0500 | [diff] [blame] | 72 | auto host = ::ipmi::getService(this->bus,IPMI_INTERFACE,IPMI_PATH); | 
|  | 73 |  | 
|  | 74 | // Start the timer for this transaction | 
|  | 75 | auto time = std::chrono::duration_cast<std::chrono::microseconds>( | 
|  | 76 | std::chrono::seconds(IPMI_SMS_ATN_ACK_TIMEOUT_SECS)); | 
|  | 77 | auto r = timer.startTimer(time); | 
|  | 78 | if (r < 0) | 
|  | 79 | { | 
|  | 80 | log<level::ERR>("Error starting timer for control host"); | 
|  | 81 | return; | 
|  | 82 | } | 
| Andrew Geissler | 1b9d4e5 | 2017-03-21 15:04:05 -0500 | [diff] [blame] | 83 |  | 
|  | 84 | auto method = this->bus.new_method_call(host.c_str(), | 
|  | 85 | IPMI_PATH.c_str(), | 
|  | 86 | IPMI_INTERFACE.c_str(), | 
|  | 87 | "setAttention"); | 
|  | 88 | auto reply = this->bus.call(method); | 
|  | 89 |  | 
|  | 90 | if (reply.is_method_error()) | 
|  | 91 | { | 
|  | 92 | log<level::ERR>("Error in setting SMS attention"); | 
|  | 93 | throw std::runtime_error("ERROR in call to setAttention"); | 
|  | 94 | } | 
|  | 95 | log<level::INFO>("SMS Attention asserted"); | 
|  | 96 | } | 
| Andrew Geissler | 0c07c32 | 2017-03-22 14:02:30 -0500 | [diff] [blame] | 97 | } | 
|  | 98 |  | 
|  | 99 | void Host::execute(base::Host::Command command) | 
|  | 100 | { | 
|  | 101 | log<level::INFO>("Pushing cmd on to queue", | 
|  | 102 | entry("CONTROL_HOST_CMD=%s", | 
|  | 103 | convertForMessage(command))); | 
|  | 104 |  | 
|  | 105 | this->workQueue.push(command); | 
|  | 106 |  | 
|  | 107 | // Alert host if this is only command in queue otherwise host will | 
|  | 108 | // be notified of next message after processing the current one | 
|  | 109 | if (this->workQueue.size() == 1) | 
|  | 110 | { | 
|  | 111 | this->checkQueue(); | 
|  | 112 | } | 
|  | 113 | else | 
|  | 114 | { | 
|  | 115 | log<level::INFO>("Command in process, no attention"); | 
|  | 116 | } | 
| Andrew Geissler | 1b9d4e5 | 2017-03-21 15:04:05 -0500 | [diff] [blame] | 117 |  | 
| Andrew Geissler | 62817fa9 | 2017-03-20 14:20:49 -0500 | [diff] [blame] | 118 | return; | 
|  | 119 | } | 
|  | 120 |  | 
| Andrew Geissler | dd2c6fd | 2017-03-16 15:53:20 -0500 | [diff] [blame] | 121 | } // namespace host | 
|  | 122 | } // namepsace phosphor |