| #include "config.h" |
| |
| #include "occ_pass_through.hpp" |
| |
| #include "elog-errors.hpp" |
| |
| #include <errno.h> |
| #include <fcntl.h> |
| #include <fmt/core.h> |
| #include <unistd.h> |
| |
| #include <org/open_power/OCC/Device/error.hpp> |
| #include <phosphor-logging/elog.hpp> |
| #include <phosphor-logging/log.hpp> |
| |
| #include <algorithm> |
| #include <memory> |
| #include <string> |
| |
| namespace open_power |
| { |
| namespace occ |
| { |
| |
| using namespace phosphor::logging; |
| using namespace sdbusplus::org::open_power::OCC::Device::Error; |
| |
| PassThrough::PassThrough( |
| const char* path |
| #ifdef POWER10 |
| , |
| std::unique_ptr<open_power::occ::powermode::PowerMode>& powerModeRef |
| #endif |
| ) : |
| Iface(utils::getBus(), path), |
| path(path), |
| #ifdef POWER10 |
| pmode(powerModeRef), |
| #endif |
| devicePath(OCC_DEV_PATH + std::to_string((this->path.back() - '0') + 1)), |
| occInstance(this->path.back() - '0'), |
| activeStatusSignal( |
| utils::getBus(), |
| sdbusRule::propertiesChanged(path, "org.open_power.OCC.Status"), |
| std::bind(std::mem_fn(&PassThrough::activeStatusEvent), this, |
| std::placeholders::_1)), |
| occCmd(occInstance, path) |
| { |
| // Nothing to do. |
| } |
| |
| std::vector<int32_t> PassThrough::send(std::vector<int32_t> command) |
| { |
| std::vector<int32_t> response{}; |
| |
| // OCC only understands [bytes] so need array of bytes. Doing this |
| // because rest-server currently treats all int* as 32 bit integer. |
| std::vector<uint8_t> cmdInBytes, rsp; |
| cmdInBytes.resize(command.size()); |
| |
| // Populate uint8_t version of vector. |
| std::transform(command.begin(), command.end(), cmdInBytes.begin(), |
| [](decltype(cmdInBytes)::value_type x) { return x; }); |
| |
| rsp = send(cmdInBytes); |
| |
| response.resize(rsp.size()); |
| std::transform(rsp.begin(), rsp.end(), response.begin(), |
| [](decltype(response)::value_type x) { return x; }); |
| |
| return response; |
| } |
| |
| std::vector<uint8_t> PassThrough::send(std::vector<uint8_t> command) |
| { |
| std::vector<uint8_t> response{}; |
| |
| log<level::DEBUG>( |
| fmt::format("PassThrough::send() Sending 0x{:02X} command to OCC{}", |
| command.front(), occInstance) |
| .c_str()); |
| CmdStatus status = occCmd.send(command, response); |
| if (status == CmdStatus::SUCCESS) |
| { |
| if (response.size() >= 5) |
| { |
| log<level::DEBUG>( |
| fmt::format("PassThrough::send() response had {} bytes", |
| response.size()) |
| .c_str()); |
| } |
| else |
| { |
| log<level::ERR>("PassThrough::send() Invalid OCC response"); |
| dump_hex(response); |
| } |
| } |
| else |
| { |
| if (status == CmdStatus::OPEN_FAILURE) |
| { |
| log<level::WARNING>("PassThrough::send() - OCC not active yet"); |
| } |
| else |
| { |
| log<level::ERR>("PassThrough::send() - OCC command failed!"); |
| } |
| } |
| |
| return response; |
| } |
| |
| bool PassThrough::setMode(const uint8_t mode, const uint16_t modeData) |
| { |
| #ifdef POWER10 |
| SysPwrMode newMode = SysPwrMode(mode); |
| |
| if ((!VALID_POWER_MODE_SETTING(newMode)) && |
| (!VALID_OEM_POWER_MODE_SETTING(newMode))) |
| { |
| log<level::ERR>( |
| fmt::format( |
| "PassThrough::setMode() Unsupported mode {} requested (0x{:04X})", |
| newMode, modeData) |
| .c_str()); |
| return false; |
| } |
| |
| if (((newMode == SysPwrMode::FFO) || (newMode == SysPwrMode::SFP)) && |
| (modeData == 0)) |
| { |
| log<level::ERR>( |
| fmt::format( |
| "PassThrough::setMode() Mode {} requires non-zero frequency point.", |
| newMode) |
| .c_str()); |
| return false; |
| } |
| |
| log<level::INFO>( |
| fmt::format("PassThrough::setMode() Setting Power Mode {} (data: {})", |
| newMode, modeData) |
| .c_str()); |
| return pmode->setMode(newMode, modeData); |
| #else |
| log<level::DEBUG>( |
| fmt::format( |
| "PassThrough::setMode() No support to setting Power Mode {} (data: {})", |
| mode, modeData) |
| .c_str()); |
| return false; |
| #endif |
| } |
| |
| // Called at OCC Status change signal |
| void PassThrough::activeStatusEvent(sdbusplus::message::message& msg) |
| { |
| std::string statusInterface; |
| std::map<std::string, std::variant<bool>> msgData; |
| msg.read(statusInterface, msgData); |
| |
| auto propertyMap = msgData.find("OccActive"); |
| if (propertyMap != msgData.end()) |
| { |
| // Extract the OccActive property |
| if (std::get<bool>(propertyMap->second)) |
| { |
| occActive = true; |
| } |
| else |
| { |
| occActive = false; |
| } |
| } |
| return; |
| } |
| |
| } // namespace occ |
| } // namespace open_power |