xref: /openbmc/openpower-occ-control/occ_manager.cpp (revision 3c1706a8c36f7d05299ca65e2f3dc9a3785566a6)
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