13e5422edSVishwanatha Subbanna #include "config.h" 294df8c90SGunnar Mills 394df8c90SGunnar Mills #include "occ_pass_through.hpp" 494df8c90SGunnar Mills 594df8c90SGunnar Mills #include "elog-errors.hpp" 694df8c90SGunnar Mills 794df8c90SGunnar Mills #include <errno.h> 894df8c90SGunnar Mills #include <fcntl.h> 994df8c90SGunnar Mills #include <unistd.h> 1094df8c90SGunnar Mills 1194df8c90SGunnar Mills #include <algorithm> 1294df8c90SGunnar Mills #include <memory> 1394df8c90SGunnar Mills #include <org/open_power/OCC/Device/error.hpp> 1494df8c90SGunnar Mills #include <phosphor-logging/elog.hpp> 1594df8c90SGunnar Mills #include <phosphor-logging/log.hpp> 1694df8c90SGunnar Mills #include <string> 176b492fbfSDeepak Kodihalli namespace open_power 186b492fbfSDeepak Kodihalli { 196b492fbfSDeepak Kodihalli namespace occ 206b492fbfSDeepak Kodihalli { 216b492fbfSDeepak Kodihalli 2294df8c90SGunnar Mills PassThrough::PassThrough(sdbusplus::bus::bus& bus, const char* path) : 2394df8c90SGunnar Mills Iface(bus, path), path(path), 243e5422edSVishwanatha Subbanna devicePath(OCC_DEV_PATH + std::to_string((this->path.back() - '0') + 1)), 253e5422edSVishwanatha Subbanna activeStatusSignal( 2694df8c90SGunnar Mills bus, sdbusRule::propertiesChanged(path, "org.open_power.OCC.Status"), 2794df8c90SGunnar Mills std::bind(std::mem_fn(&PassThrough::activeStatusEvent), this, 2894df8c90SGunnar Mills std::placeholders::_1)) 296b492fbfSDeepak Kodihalli { 3038b08d79SVishwanatha Subbanna // Nothing to do. 3138b08d79SVishwanatha Subbanna } 3238b08d79SVishwanatha Subbanna 333e5422edSVishwanatha Subbanna void PassThrough::openDevice() 3438b08d79SVishwanatha Subbanna { 359bb065b8SVishwanatha Subbanna using namespace phosphor::logging; 36ee4d83dfSVishwanatha Subbanna using namespace sdbusplus::org::open_power::OCC::Device::Error; 379bb065b8SVishwanatha Subbanna 384f4712d8SEddie James if (!occActive) 394f4712d8SEddie James { 404f4712d8SEddie James log<level::INFO>("OCC is inactive; cannot perform pass-through"); 414f4712d8SEddie James return; 424f4712d8SEddie James } 434f4712d8SEddie James 443e5422edSVishwanatha Subbanna fd = open(devicePath.c_str(), O_RDWR | O_NONBLOCK); 4538b08d79SVishwanatha Subbanna if (fd < 0) 4638b08d79SVishwanatha Subbanna { 479bb065b8SVishwanatha Subbanna // This would log and terminate since its not handled. 489bb065b8SVishwanatha Subbanna elog<OpenFailure>( 4994df8c90SGunnar Mills phosphor::logging::org::open_power::OCC::Device::OpenFailure:: 5094df8c90SGunnar Mills CALLOUT_ERRNO(errno), 5194df8c90SGunnar Mills phosphor::logging::org::open_power::OCC::Device::OpenFailure:: 5294df8c90SGunnar Mills CALLOUT_DEVICE_PATH(devicePath.c_str())); 5338b08d79SVishwanatha Subbanna } 543e5422edSVishwanatha Subbanna return; 553e5422edSVishwanatha Subbanna } 563e5422edSVishwanatha Subbanna 573e5422edSVishwanatha Subbanna void PassThrough::closeDevice() 583e5422edSVishwanatha Subbanna { 593e5422edSVishwanatha Subbanna if (fd >= 0) 603e5422edSVishwanatha Subbanna { 613e5422edSVishwanatha Subbanna close(fd); 624f4712d8SEddie James fd = -1; 633e5422edSVishwanatha Subbanna } 646b492fbfSDeepak Kodihalli } 656b492fbfSDeepak Kodihalli 666b492fbfSDeepak Kodihalli std::vector<int32_t> PassThrough::send(std::vector<int32_t> command) 676b492fbfSDeepak Kodihalli { 6867d50ad6SVishwanatha Subbanna using namespace phosphor::logging; 69ee4d83dfSVishwanatha Subbanna using namespace sdbusplus::org::open_power::OCC::Device::Error; 7067d50ad6SVishwanatha Subbanna 7167d50ad6SVishwanatha Subbanna std::vector<int32_t> response{}; 7267d50ad6SVishwanatha Subbanna 734f4712d8SEddie James openDevice(); 744f4712d8SEddie James 754f4712d8SEddie James if (fd < 0) 764f4712d8SEddie James { 774f4712d8SEddie James // OCC is inactive; empty response 784f4712d8SEddie James return response; 794f4712d8SEddie James } 804f4712d8SEddie James 817d700e26SVishwanatha Subbanna // OCC only understands [bytes] so need array of bytes. Doing this 827d700e26SVishwanatha Subbanna // because rest-server currently treats all int* as 32 bit integer. 837d700e26SVishwanatha Subbanna std::vector<uint8_t> cmdInBytes; 847d700e26SVishwanatha Subbanna cmdInBytes.resize(command.size()); 857d700e26SVishwanatha Subbanna 867d700e26SVishwanatha Subbanna // Populate uint8_t version of vector. 877d700e26SVishwanatha Subbanna std::transform(command.begin(), command.end(), cmdInBytes.begin(), 887d700e26SVishwanatha Subbanna [](decltype(cmdInBytes)::value_type x) { return x; }); 897d700e26SVishwanatha Subbanna 907d700e26SVishwanatha Subbanna ssize_t size = cmdInBytes.size() * sizeof(decltype(cmdInBytes)::value_type); 913e5422edSVishwanatha Subbanna auto rc = write(fd, cmdInBytes.data(), size); 9267d50ad6SVishwanatha Subbanna if (rc < 0 || (rc != size)) 9367d50ad6SVishwanatha Subbanna { 949bb065b8SVishwanatha Subbanna // This would log and terminate since its not handled. 959bb065b8SVishwanatha Subbanna elog<WriteFailure>( 9694df8c90SGunnar Mills phosphor::logging::org::open_power::OCC::Device::WriteFailure:: 9794df8c90SGunnar Mills CALLOUT_ERRNO(errno), 9894df8c90SGunnar Mills phosphor::logging::org::open_power::OCC::Device::WriteFailure:: 9994df8c90SGunnar Mills CALLOUT_DEVICE_PATH(devicePath.c_str())); 1006b492fbfSDeepak Kodihalli } 1016b492fbfSDeepak Kodihalli 10267d50ad6SVishwanatha Subbanna // Now read the response. This would be the content of occ-sram 10367d50ad6SVishwanatha Subbanna while (1) 10467d50ad6SVishwanatha Subbanna { 1057d700e26SVishwanatha Subbanna uint8_t data{}; 1063e5422edSVishwanatha Subbanna auto len = read(fd, &data, sizeof(data)); 10767d50ad6SVishwanatha Subbanna if (len > 0) 10867d50ad6SVishwanatha Subbanna { 10967d50ad6SVishwanatha Subbanna response.emplace_back(data); 11067d50ad6SVishwanatha Subbanna } 11167d50ad6SVishwanatha Subbanna else if (len < 0 && errno == EAGAIN) 11267d50ad6SVishwanatha Subbanna { 1139bb065b8SVishwanatha Subbanna // We may have data coming still. 1149bb065b8SVishwanatha Subbanna // This driver does not need a sleep for a retry. 11567d50ad6SVishwanatha Subbanna continue; 11667d50ad6SVishwanatha Subbanna } 11767d50ad6SVishwanatha Subbanna else if (len == 0) 11867d50ad6SVishwanatha Subbanna { 11967d50ad6SVishwanatha Subbanna // We have read all that we can. 12067d50ad6SVishwanatha Subbanna break; 12167d50ad6SVishwanatha Subbanna } 12267d50ad6SVishwanatha Subbanna else 12367d50ad6SVishwanatha Subbanna { 1249bb065b8SVishwanatha Subbanna // This would log and terminate since its not handled. 1259bb065b8SVishwanatha Subbanna elog<ReadFailure>( 12694df8c90SGunnar Mills phosphor::logging::org::open_power::OCC::Device::ReadFailure:: 12794df8c90SGunnar Mills CALLOUT_ERRNO(errno), 12894df8c90SGunnar Mills phosphor::logging::org::open_power::OCC::Device::ReadFailure:: 12994df8c90SGunnar Mills CALLOUT_DEVICE_PATH(devicePath.c_str())); 13067d50ad6SVishwanatha Subbanna } 13167d50ad6SVishwanatha Subbanna } 13267d50ad6SVishwanatha Subbanna 1334f4712d8SEddie James closeDevice(); 1344f4712d8SEddie James 13567d50ad6SVishwanatha Subbanna return response; 13667d50ad6SVishwanatha Subbanna } 13767d50ad6SVishwanatha Subbanna 1383e5422edSVishwanatha Subbanna // Called at OCC Status change signal 1393e5422edSVishwanatha Subbanna void PassThrough::activeStatusEvent(sdbusplus::message::message& msg) 1403e5422edSVishwanatha Subbanna { 1413e5422edSVishwanatha Subbanna std::string statusInterface; 1423e5422edSVishwanatha Subbanna std::map<std::string, sdbusplus::message::variant<bool>> msgData; 1433e5422edSVishwanatha Subbanna msg.read(statusInterface, msgData); 1443e5422edSVishwanatha Subbanna 1453e5422edSVishwanatha Subbanna auto propertyMap = msgData.find("OccActive"); 1463e5422edSVishwanatha Subbanna if (propertyMap != msgData.end()) 1473e5422edSVishwanatha Subbanna { 1483e5422edSVishwanatha Subbanna // Extract the OccActive property 149*305ff8b1SPatrick Williams if (std::get<bool>(propertyMap->second)) 1503e5422edSVishwanatha Subbanna { 1514f4712d8SEddie James occActive = true; 1523e5422edSVishwanatha Subbanna } 1533e5422edSVishwanatha Subbanna else 1543e5422edSVishwanatha Subbanna { 1554f4712d8SEddie James occActive = false; 1563e5422edSVishwanatha Subbanna this->closeDevice(); 1573e5422edSVishwanatha Subbanna } 1583e5422edSVishwanatha Subbanna } 1593e5422edSVishwanatha Subbanna return; 1603e5422edSVishwanatha Subbanna } 1613e5422edSVishwanatha Subbanna 1626b492fbfSDeepak Kodihalli } // namespace occ 1636b492fbfSDeepak Kodihalli } // namespace open_power 164