1 #include "config.h" 2 3 #include "occ_manager.hpp" 4 5 #include "i2c_occ.hpp" 6 #include "occ_finder.hpp" 7 #include "utils.hpp" 8 9 #include <experimental/filesystem> 10 #include <phosphor-logging/elog-errors.hpp> 11 #include <phosphor-logging/log.hpp> 12 #include <xyz/openbmc_project/Common/error.hpp> 13 14 namespace open_power 15 { 16 namespace occ 17 { 18 19 void Manager::findAndCreateObjects() 20 { 21 for (auto id = 0; id < MAX_CPUS; ++id) 22 { 23 // Create one occ per cpu 24 auto occ = std::string(OCC_NAME) + std::to_string(id); 25 createObjects(occ); 26 } 27 } 28 29 int Manager::cpuCreated(sdbusplus::message::message& msg) 30 { 31 namespace fs = std::experimental::filesystem; 32 33 sdbusplus::message::object_path o; 34 msg.read(o); 35 fs::path cpuPath(std::string(std::move(o))); 36 37 auto name = cpuPath.filename().string(); 38 auto index = name.find(CPU_NAME); 39 name.replace(index, std::strlen(CPU_NAME), OCC_NAME); 40 41 createObjects(name); 42 43 return 0; 44 } 45 46 void Manager::createObjects(const std::string& occ) 47 { 48 auto path = fs::path(OCC_CONTROL_ROOT) / occ; 49 50 passThroughObjects.emplace_back( 51 std::make_unique<PassThrough>(bus, path.c_str())); 52 53 statusObjects.emplace_back(std::make_unique<Status>( 54 bus, event, path.c_str(), *this, 55 std::bind(std::mem_fn(&Manager::statusCallBack), this, 56 std::placeholders::_1))); 57 58 // Create the power cap monitor object for master occ (0) 59 if (!pcap) 60 { 61 pcap = std::make_unique<open_power::occ::powercap::PowerCap>( 62 bus, *statusObjects.front()); 63 } 64 } 65 66 void Manager::statusCallBack(bool status) 67 { 68 using namespace phosphor::logging; 69 using InternalFailure = 70 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 71 72 // At this time, it won't happen but keeping it 73 // here just in case something changes in the future 74 if ((activeCount == 0) && (!status)) 75 { 76 log<level::ERR>("Invalid update on OCCActive"); 77 elog<InternalFailure>(); 78 } 79 80 activeCount += status ? 1 : -1; 81 82 // Only start presence detection if all the OCCs are bound 83 if (activeCount == statusObjects.size()) 84 { 85 for (auto& obj : statusObjects) 86 { 87 obj->addPresenceWatchMaster(); 88 } 89 } 90 } 91 92 #ifdef I2C_OCC 93 void Manager::initStatusObjects() 94 { 95 // Make sure we have a valid path string 96 static_assert(sizeof(DEV_PATH) != 0); 97 98 auto deviceNames = i2c_occ::getOccHwmonDevices(DEV_PATH); 99 auto occMasterName = deviceNames.front(); 100 for (auto& name : deviceNames) 101 { 102 i2c_occ::i2cToDbus(name); 103 name = std::string(OCC_NAME) + '_' + name; 104 auto path = fs::path(OCC_CONTROL_ROOT) / name; 105 statusObjects.emplace_back( 106 std::make_unique<Status>(bus, event, path.c_str(), *this)); 107 } 108 // The first device is master occ 109 pcap = std::make_unique<open_power::occ::powercap::PowerCap>( 110 bus, *statusObjects.front(), occMasterName); 111 } 112 #endif 113 114 } // namespace occ 115 } // namespace open_power 116