| 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" | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 6 |  | 
| Vernon Mauery | 6a98fe7 | 2019-03-11 15:57:48 -0700 | [diff] [blame] | 7 | #include <ipmid/utils.hpp> | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 8 | #include <phosphor-logging/elog-errors.hpp> | 
| George Liu | 59d6dbb | 2024-07-17 20:20:32 +0800 | [diff] [blame^] | 9 | #include <phosphor-logging/lg2.hpp> | 
| William A. Kennington III | 4c00802 | 2018-10-12 17:18:14 -0700 | [diff] [blame] | 10 | #include <sdbusplus/message/types.hpp> | 
| Vernon Mauery | 1181af7 | 2018-10-08 12:05:00 -0700 | [diff] [blame] | 11 | #include <sdbusplus/timer.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 |  | 
| Patrick Williams | fbc6c9d | 2023-05-10 07:50:16 -0500 | [diff] [blame] | 15 | #include <chrono> | 
 | 16 |  | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 17 | namespace phosphor | 
 | 18 | { | 
 | 19 | namespace host | 
 | 20 | { | 
 | 21 | namespace command | 
 | 22 | { | 
 | 23 |  | 
| Matt Spinler | 15309ef | 2018-06-27 13:01:25 -0500 | [diff] [blame] | 24 | constexpr auto HOST_STATE_PATH = "/xyz/openbmc_project/state/host0"; | 
 | 25 | constexpr auto HOST_STATE_INTERFACE = "xyz.openbmc_project.State.Host"; | 
 | 26 | constexpr auto HOST_TRANS_PROP = "RequestedHostTransition"; | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 27 |  | 
 | 28 | // For throwing exceptions | 
 | 29 | using namespace phosphor::logging; | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 30 | using InternalFailure = | 
| Willy Tu | 523e2d1 | 2023-09-05 11:36:48 -0700 | [diff] [blame] | 31 |     sdbusplus::error::xyz::openbmc_project::common::InternalFailure; | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 32 |  | 
| Matt Spinler | 15309ef | 2018-06-27 13:01:25 -0500 | [diff] [blame] | 33 | namespace sdbusRule = sdbusplus::bus::match::rules; | 
 | 34 |  | 
| Patrick Williams | 5d82f47 | 2022-07-22 19:26:53 -0500 | [diff] [blame] | 35 | Manager::Manager(sdbusplus::bus_t& bus) : | 
| Vernon Mauery | 316f23d | 2018-10-29 13:34:26 -0700 | [diff] [blame] | 36 |     bus(bus), timer(std::bind(&Manager::hostTimeout, this)), | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 37 |     hostTransitionMatch( | 
 | 38 |         bus, | 
 | 39 |         sdbusRule::propertiesChanged(HOST_STATE_PATH, HOST_STATE_INTERFACE), | 
 | 40 |         std::bind(&Manager::clearQueueOnPowerOn, this, std::placeholders::_1)) | 
| Vishwanatha Subbanna | 6e8979d | 2017-07-13 16:48:20 +0530 | [diff] [blame] | 41 | { | 
 | 42 |     // Nothing to do here. | 
 | 43 | } | 
 | 44 |  | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 45 | // Called as part of READ_MSG_DATA command | 
 | 46 | IpmiCmdData Manager::getNextCommand() | 
 | 47 | { | 
 | 48 |     // Stop the timer. Don't have to Err failure doing so. | 
| Vernon Mauery | 1181af7 | 2018-10-08 12:05:00 -0700 | [diff] [blame] | 49 |     auto r = timer.stop(); | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 50 |     if (r < 0) | 
 | 51 |     { | 
| George Liu | 59d6dbb | 2024-07-17 20:20:32 +0800 | [diff] [blame^] | 52 |         lg2::error("Failure to STOP the timer: {ERROR}", "ERROR", strerror(-r)); | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 53 |     } | 
 | 54 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 55 |     if (this->workQueue.empty()) | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 56 |     { | 
 | 57 |         // Just return a heartbeat in this case.  A spurious SMS_ATN was | 
 | 58 |         // asserted for the host (probably from a previous boot). | 
| George Liu | 59d6dbb | 2024-07-17 20:20:32 +0800 | [diff] [blame^] | 59 |         lg2::debug("Control Host work queue is empty!"); | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 60 |  | 
 | 61 |         return std::make_pair(CMD_HEARTBEAT, 0x00); | 
 | 62 |     } | 
 | 63 |  | 
 | 64 |     // Pop the processed entry off the queue | 
 | 65 |     auto command = this->workQueue.front(); | 
 | 66 |     this->workQueue.pop(); | 
 | 67 |  | 
 | 68 |     // IPMI command is the first element in pair | 
 | 69 |     auto ipmiCmdData = std::get<0>(command); | 
 | 70 |  | 
 | 71 |     // Now, call the user registered functions so that | 
 | 72 |     // implementation specific CommandComplete signals | 
 | 73 |     // can be sent. `true` indicating Success. | 
 | 74 |     std::get<CallBack>(command)(ipmiCmdData, true); | 
 | 75 |  | 
 | 76 |     // Check for another entry in the queue and kick it off | 
 | 77 |     this->checkQueueAndAlertHost(); | 
 | 78 |  | 
 | 79 |     // Tuple of command and data | 
 | 80 |     return ipmiCmdData; | 
 | 81 | } | 
 | 82 |  | 
 | 83 | // Called when initial timer goes off post sending SMS_ATN | 
 | 84 | void Manager::hostTimeout() | 
 | 85 | { | 
| George Liu | 59d6dbb | 2024-07-17 20:20:32 +0800 | [diff] [blame^] | 86 |     lg2::error("Host control timeout hit!"); | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 87 |  | 
| Matt Spinler | 15309ef | 2018-06-27 13:01:25 -0500 | [diff] [blame] | 88 |     clearQueue(); | 
 | 89 | } | 
 | 90 |  | 
 | 91 | void Manager::clearQueue() | 
 | 92 | { | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 93 |     // Dequeue all entries and send fail signal | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 94 |     while (!this->workQueue.empty()) | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 95 |     { | 
 | 96 |         auto command = this->workQueue.front(); | 
 | 97 |         this->workQueue.pop(); | 
 | 98 |  | 
 | 99 |         // IPMI command is the first element in pair | 
 | 100 |         auto ipmiCmdData = std::get<0>(command); | 
 | 101 |  | 
 | 102 |         // Call the implementation specific Command Failure. | 
 | 103 |         // `false` indicating Failure | 
 | 104 |         std::get<CallBack>(command)(ipmiCmdData, false); | 
 | 105 |     } | 
 | 106 | } | 
 | 107 |  | 
 | 108 | // Called for alerting the host | 
 | 109 | void Manager::checkQueueAndAlertHost() | 
 | 110 | { | 
 | 111 |     if (this->workQueue.size() >= 1) | 
 | 112 |     { | 
| George Liu | 59d6dbb | 2024-07-17 20:20:32 +0800 | [diff] [blame^] | 113 |         lg2::debug("Asserting SMS Attention"); | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 114 |  | 
| Andrew Geissler | b18c8bc | 2020-08-05 15:54:44 -0500 | [diff] [blame] | 115 |         std::string HOST_IPMI_SVC("org.openbmc.HostIpmi"); | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 116 |         std::string IPMI_PATH("/org/openbmc/HostIpmi/1"); | 
 | 117 |         std::string IPMI_INTERFACE("org.openbmc.HostIpmi"); | 
 | 118 |  | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 119 |         // Start the timer for this transaction | 
 | 120 |         auto time = std::chrono::duration_cast<std::chrono::microseconds>( | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 121 |             std::chrono::seconds(IPMI_SMS_ATN_ACK_TIMEOUT_SECS)); | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 122 |  | 
| Vernon Mauery | 1181af7 | 2018-10-08 12:05:00 -0700 | [diff] [blame] | 123 |         auto r = timer.start(time); | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 124 |         if (r < 0) | 
 | 125 |         { | 
| George Liu | 59d6dbb | 2024-07-17 20:20:32 +0800 | [diff] [blame^] | 126 |             lg2::error("Error starting timer for control host"); | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 127 |             return; | 
 | 128 |         } | 
 | 129 |  | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 130 |         auto method = | 
| Andrew Geissler | b18c8bc | 2020-08-05 15:54:44 -0500 | [diff] [blame] | 131 |             this->bus.new_method_call(HOST_IPMI_SVC.c_str(), IPMI_PATH.c_str(), | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 132 |                                       IPMI_INTERFACE.c_str(), "setAttention"); | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 133 |  | 
| Thang Tran | 897ae72 | 2022-03-06 10:26:18 +0700 | [diff] [blame] | 134 |         try | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 135 |         { | 
| Thang Tran | 897ae72 | 2022-03-06 10:26:18 +0700 | [diff] [blame] | 136 |             auto reply = this->bus.call(method); | 
 | 137 |  | 
| George Liu | 59d6dbb | 2024-07-17 20:20:32 +0800 | [diff] [blame^] | 138 |             lg2::debug("SMS Attention asserted"); | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 139 |         } | 
| Patrick Williams | 5d82f47 | 2022-07-22 19:26:53 -0500 | [diff] [blame] | 140 |         catch (sdbusplus::exception_t& e) | 
| Thang Tran | 897ae72 | 2022-03-06 10:26:18 +0700 | [diff] [blame] | 141 |         { | 
| George Liu | 59d6dbb | 2024-07-17 20:20:32 +0800 | [diff] [blame^] | 142 |             lg2::error("Error when call setAttention method"); | 
| Thang Tran | 897ae72 | 2022-03-06 10:26:18 +0700 | [diff] [blame] | 143 |         } | 
| 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 | { | 
| George Liu | 59d6dbb | 2024-07-17 20:20:32 +0800 | [diff] [blame^] | 150 |     lg2::debug("Pushing cmd on to queue, command: {COMMAND}", "COMMAND", | 
 | 151 |                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 |     { | 
| George Liu | 59d6dbb | 2024-07-17 20:20:32 +0800 | [diff] [blame^] | 163 |         lg2::info("Command in process, no attention"); | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 164 |     } | 
 | 165 |  | 
 | 166 |     return; | 
 | 167 | } | 
 | 168 |  | 
| Patrick Williams | 5d82f47 | 2022-07-22 19:26:53 -0500 | [diff] [blame] | 169 | void Manager::clearQueueOnPowerOn(sdbusplus::message_t& msg) | 
| Matt Spinler | 15309ef | 2018-06-27 13:01:25 -0500 | [diff] [blame] | 170 | { | 
| Willy Tu | 523e2d1 | 2023-09-05 11:36:48 -0700 | [diff] [blame] | 171 |     namespace server = sdbusplus::server::xyz::openbmc_project::state; | 
| Matt Spinler | 15309ef | 2018-06-27 13:01:25 -0500 | [diff] [blame] | 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 |  | 
| William A. Kennington III | 4c00802 | 2018-10-12 17:18:14 -0700 | [diff] [blame] | 183 |     auto& requestedState = | 
| Vernon Mauery | f442e11 | 2019-04-09 11:44:36 -0700 | [diff] [blame] | 184 |         std::get<std::string>(properties.at(HOST_TRANS_PROP)); | 
| Matt Spinler | 15309ef | 2018-06-27 13:01:25 -0500 | [diff] [blame] | 185 |  | 
 | 186 |     if (server::Host::convertTransitionFromString(requestedState) == | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 187 |         server::Host::Transition::On) | 
| Matt Spinler | 15309ef | 2018-06-27 13:01:25 -0500 | [diff] [blame] | 188 |     { | 
 | 189 |         clearQueue(); | 
 | 190 |     } | 
 | 191 | } | 
 | 192 |  | 
| Vishwanatha Subbanna | ac149a9 | 2017-07-11 18:16:50 +0530 | [diff] [blame] | 193 | } // namespace command | 
 | 194 | } // namespace host | 
| Patrick Venture | 0b02be9 | 2018-08-31 11:55:55 -0700 | [diff] [blame] | 195 | } // namespace phosphor |