| Patrick Venture | 46470a3 | 2018-09-07 19:26:25 -0700 | [diff] [blame] | 1 | #include "config.h" | 
|  | 2 |  | 
|  | 3 | #include "host-cmd-manager.hpp" | 
|  | 4 |  | 
|  | 5 | #include "systemintfcmds.hpp" | 
|  | 6 | #include "timer.hpp" | 
|  | 7 | #include "utils.hpp" | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 8 |  | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 9 | #include <chrono> | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 10 | #include <phosphor-logging/elog-errors.hpp> | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 11 | #include <phosphor-logging/log.hpp> | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 12 | #include <xyz/openbmc_project/Common/error.hpp> | 
| Matt Spinler | 15309ef | 2018-06-27 13:01:25 -0500 | [diff] [blame] | 13 | #include <xyz/openbmc_project/State/Host/server.hpp> | 
| Vishwanatha Subbanna | 6e8979d | 2017-07-13 16:48:20 +0530 | [diff] [blame] | 14 |  | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 15 | namespace phosphor | 
|  | 16 | { | 
|  | 17 | namespace host | 
|  | 18 | { | 
|  | 19 | namespace command | 
|  | 20 | { | 
|  | 21 |  | 
|  | 22 | constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper"; | 
|  | 23 | constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper"; | 
|  | 24 | constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper"; | 
| Matt Spinler | 15309ef | 2018-06-27 13:01:25 -0500 | [diff] [blame] | 25 | constexpr auto HOST_STATE_PATH = "/xyz/openbmc_project/state/host0"; | 
|  | 26 | constexpr auto HOST_STATE_INTERFACE = "xyz.openbmc_project.State.Host"; | 
|  | 27 | constexpr auto HOST_TRANS_PROP = "RequestedHostTransition"; | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 28 |  | 
|  | 29 | // For throwing exceptions | 
|  | 30 | using namespace phosphor::logging; | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 31 | using InternalFailure = | 
|  | 32 | sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 33 |  | 
| Matt Spinler | 15309ef | 2018-06-27 13:01:25 -0500 | [diff] [blame] | 34 | namespace sdbusRule = sdbusplus::bus::match::rules; | 
|  | 35 |  | 
| Vishwanatha Subbanna | 6e8979d | 2017-07-13 16:48:20 +0530 | [diff] [blame] | 36 | Manager::Manager(sdbusplus::bus::bus& bus, sd_event* event) : | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 37 | bus(bus), timer(event, std::bind(&Manager::hostTimeout, this)), | 
|  | 38 | hostTransitionMatch( | 
|  | 39 | bus, | 
|  | 40 | sdbusRule::propertiesChanged(HOST_STATE_PATH, HOST_STATE_INTERFACE), | 
|  | 41 | std::bind(&Manager::clearQueueOnPowerOn, this, std::placeholders::_1)) | 
| Vishwanatha Subbanna | 6e8979d | 2017-07-13 16:48:20 +0530 | [diff] [blame] | 42 | { | 
|  | 43 | // Nothing to do here. | 
|  | 44 | } | 
|  | 45 |  | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 46 | // Called as part of READ_MSG_DATA command | 
|  | 47 | IpmiCmdData Manager::getNextCommand() | 
|  | 48 | { | 
|  | 49 | // Stop the timer. Don't have to Err failure doing so. | 
|  | 50 | auto r = timer.setTimer(SD_EVENT_OFF); | 
|  | 51 | if (r < 0) | 
|  | 52 | { | 
|  | 53 | log<level::ERR>("Failure to STOP the timer", | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 54 | entry("ERROR=%s", strerror(-r))); | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 55 | } | 
|  | 56 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 57 | if (this->workQueue.empty()) | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 58 | { | 
|  | 59 | // Just return a heartbeat in this case.  A spurious SMS_ATN was | 
|  | 60 | // asserted for the host (probably from a previous boot). | 
| Aditya Saripalli | 5fb1460 | 2017-11-09 14:46:27 +0530 | [diff] [blame] | 61 | log<level::DEBUG>("Control Host work queue is empty!"); | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 62 |  | 
|  | 63 | return std::make_pair(CMD_HEARTBEAT, 0x00); | 
|  | 64 | } | 
|  | 65 |  | 
|  | 66 | // Pop the processed entry off the queue | 
|  | 67 | auto command = this->workQueue.front(); | 
|  | 68 | this->workQueue.pop(); | 
|  | 69 |  | 
|  | 70 | // IPMI command is the first element in pair | 
|  | 71 | auto ipmiCmdData = std::get<0>(command); | 
|  | 72 |  | 
|  | 73 | // Now, call the user registered functions so that | 
|  | 74 | // implementation specific CommandComplete signals | 
|  | 75 | // can be sent. `true` indicating Success. | 
|  | 76 | std::get<CallBack>(command)(ipmiCmdData, true); | 
|  | 77 |  | 
|  | 78 | // Check for another entry in the queue and kick it off | 
|  | 79 | this->checkQueueAndAlertHost(); | 
|  | 80 |  | 
|  | 81 | // Tuple of command and data | 
|  | 82 | return ipmiCmdData; | 
|  | 83 | } | 
|  | 84 |  | 
|  | 85 | // Called when initial timer goes off post sending SMS_ATN | 
|  | 86 | void Manager::hostTimeout() | 
|  | 87 | { | 
|  | 88 | log<level::ERR>("Host control timeout hit!"); | 
|  | 89 |  | 
| Matt Spinler | 15309ef | 2018-06-27 13:01:25 -0500 | [diff] [blame] | 90 | clearQueue(); | 
|  | 91 | } | 
|  | 92 |  | 
|  | 93 | void Manager::clearQueue() | 
|  | 94 | { | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 95 | // Dequeue all entries and send fail signal | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 96 | while (!this->workQueue.empty()) | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 97 | { | 
|  | 98 | auto command = this->workQueue.front(); | 
|  | 99 | this->workQueue.pop(); | 
|  | 100 |  | 
|  | 101 | // IPMI command is the first element in pair | 
|  | 102 | auto ipmiCmdData = std::get<0>(command); | 
|  | 103 |  | 
|  | 104 | // Call the implementation specific Command Failure. | 
|  | 105 | // `false` indicating Failure | 
|  | 106 | std::get<CallBack>(command)(ipmiCmdData, false); | 
|  | 107 | } | 
|  | 108 | } | 
|  | 109 |  | 
|  | 110 | // Called for alerting the host | 
|  | 111 | void Manager::checkQueueAndAlertHost() | 
|  | 112 | { | 
|  | 113 | if (this->workQueue.size() >= 1) | 
|  | 114 | { | 
| Aditya Saripalli | 5fb1460 | 2017-11-09 14:46:27 +0530 | [diff] [blame] | 115 | log<level::DEBUG>("Asserting SMS Attention"); | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 116 |  | 
|  | 117 | std::string IPMI_PATH("/org/openbmc/HostIpmi/1"); | 
|  | 118 | std::string IPMI_INTERFACE("org.openbmc.HostIpmi"); | 
|  | 119 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 120 | auto host = ::ipmi::getService(this->bus, IPMI_INTERFACE, IPMI_PATH); | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 121 |  | 
|  | 122 | // Start the timer for this transaction | 
|  | 123 | auto time = std::chrono::duration_cast<std::chrono::microseconds>( | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 124 | std::chrono::seconds(IPMI_SMS_ATN_ACK_TIMEOUT_SECS)); | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 125 |  | 
|  | 126 | auto r = timer.startTimer(time); | 
|  | 127 | if (r < 0) | 
|  | 128 | { | 
|  | 129 | log<level::ERR>("Error starting timer for control host"); | 
|  | 130 | return; | 
|  | 131 | } | 
|  | 132 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 133 | auto method = | 
|  | 134 | this->bus.new_method_call(host.c_str(), IPMI_PATH.c_str(), | 
|  | 135 | IPMI_INTERFACE.c_str(), "setAttention"); | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 136 | auto reply = this->bus.call(method); | 
|  | 137 |  | 
|  | 138 | if (reply.is_method_error()) | 
|  | 139 | { | 
|  | 140 | log<level::ERR>("Error in setting SMS attention"); | 
|  | 141 | elog<InternalFailure>(); | 
|  | 142 | } | 
| Aditya Saripalli | 5fb1460 | 2017-11-09 14:46:27 +0530 | [diff] [blame] | 143 | log<level::DEBUG>("SMS Attention asserted"); | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 144 | } | 
|  | 145 | } | 
|  | 146 |  | 
|  | 147 | // Called by specific implementations that provide commands | 
|  | 148 | void Manager::execute(CommandHandler command) | 
|  | 149 | { | 
| Aditya Saripalli | 5fb1460 | 2017-11-09 14:46:27 +0530 | [diff] [blame] | 150 | log<level::DEBUG>("Pushing cmd on to queue", | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 151 | entry("COMMAND=%d", std::get<0>(command).first)); | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 152 |  | 
|  | 153 | this->workQueue.emplace(command); | 
|  | 154 |  | 
|  | 155 | // Alert host if this is only command in queue otherwise host will | 
|  | 156 | // be notified of next message after processing the current one | 
|  | 157 | if (this->workQueue.size() == 1) | 
|  | 158 | { | 
|  | 159 | this->checkQueueAndAlertHost(); | 
|  | 160 | } | 
|  | 161 | else | 
|  | 162 | { | 
|  | 163 | log<level::INFO>("Command in process, no attention"); | 
|  | 164 | } | 
|  | 165 |  | 
|  | 166 | return; | 
|  | 167 | } | 
|  | 168 |  | 
| Matt Spinler | 15309ef | 2018-06-27 13:01:25 -0500 | [diff] [blame] | 169 | void Manager::clearQueueOnPowerOn(sdbusplus::message::message& msg) | 
|  | 170 | { | 
|  | 171 | namespace server = sdbusplus::xyz::openbmc_project::State::server; | 
|  | 172 |  | 
|  | 173 | ::ipmi::DbusInterface interface; | 
|  | 174 | ::ipmi::PropertyMap properties; | 
|  | 175 |  | 
|  | 176 | msg.read(interface, properties); | 
|  | 177 |  | 
|  | 178 | if (properties.find(HOST_TRANS_PROP) == properties.end()) | 
|  | 179 | { | 
|  | 180 | return; | 
|  | 181 | } | 
|  | 182 |  | 
|  | 183 | auto& requestedState = properties.at(HOST_TRANS_PROP).get<std::string>(); | 
|  | 184 |  | 
|  | 185 | if (server::Host::convertTransitionFromString(requestedState) == | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 186 | server::Host::Transition::On) | 
| Matt Spinler | 15309ef | 2018-06-27 13:01:25 -0500 | [diff] [blame] | 187 | { | 
|  | 188 | clearQueue(); | 
|  | 189 | } | 
|  | 190 | } | 
|  | 191 |  | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 192 | } // namespace command | 
|  | 193 | } // namespace host | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 194 | } // namespace phosphor |