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