blob: 09cefccfc012e2d1fc7fd986c6474707be224676 [file] [log] [blame]
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +05301#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
11namespace open_power
12{
13namespace occ
14{
15
16void Manager::findAndCreateObjects()
17{
18 // Check if CPU inventory exists already.
19 auto occs = open_power::occ::finder::get(bus);
20 if (occs.empty())
21 {
22 // Need to watch for CPU inventory creation.
23 for (auto id = 0; id < MAX_CPUS; ++id)
24 {
25 auto path = std::string(CPU_PATH) + std::to_string(id);
26 cpuMatches.emplace_back(
27 bus,
28 sdbusRule::interfacesAdded() +
29 sdbusRule::argNpath(0, path),
30 std::bind(std::mem_fn(&Manager::cpuCreated),
31 this, std::placeholders::_1));
32 }
33 }
34 else
35 {
36 for (const auto& occ : occs)
37 {
38 // CPU inventory exists already, OCC objects can be created.
39 createObjects(occ);
40 }
41 }
42}
43
44int Manager::cpuCreated(sdbusplus::message::message& msg)
45{
46 namespace fs = std::experimental::filesystem;
47
48 sdbusplus::message::object_path o;
49 msg.read(o);
50 fs::path cpuPath(std::string(std::move(o)));
51
52 auto name = cpuPath.filename().string();
53 auto index = name.find(CPU_NAME);
54 name.replace(index, std::strlen(CPU_NAME), OCC_NAME);
55
56 createObjects(name);
57
58 return 0;
59}
60
61void Manager::createObjects(const std::string& occ)
62{
63 auto path = fs::path(OCC_CONTROL_ROOT) / occ;
64
65 passThroughObjects.emplace_back(
66 std::make_unique<PassThrough>(
67 bus,
68 path.c_str()));
69
70 statusObjects.emplace_back(
71 std::make_unique<Status>(
72 bus,
73 event,
74 path.c_str(),
75 std::bind(std::mem_fn(&Manager::statusCallBack),
76 this, std::placeholders::_1)));
77
78 // Create the power cap monitor object for master occ (0)
79 if (!pcap)
80 {
81 pcap = std::make_unique<open_power::occ::powercap::PowerCap>(
82 bus,
83 *statusObjects.front());
84 }
85}
86
87void Manager::statusCallBack(bool status)
88{
89 using namespace phosphor::logging;
90 using InternalFailure = sdbusplus::xyz::openbmc_project::Common::
91 Error::InternalFailure;
92
93 // At this time, it won't happen but keeping it
94 // here just in case something changes in the future
95 if ((activeCount == 0) && (!status))
96 {
97 log<level::ERR>("Invalid update on OCCActive");
98 elog<InternalFailure>();
99 }
100
101 activeCount += status ? 1 : -1;
102
103 // If all the OCCs are bound, then start error detection
104 if (activeCount == statusObjects.size())
105 {
106 for (const auto& occ: statusObjects)
107 {
108 occ->addErrorWatch();
109 }
110 }
111 else if (!status)
112 {
113 // If some OCCs are not bound yet, those will be a NO-OP
114 for (const auto& occ: statusObjects)
115 {
116 occ->removeErrorWatch();
117 }
118 }
119}
120
121#ifdef I2C_OCC
122void Manager::initStatusObjects()
123{
124 // Make sure we have a valid path string
125 static_assert(sizeof(DEV_PATH) != 0);
126
127 auto deviceNames = i2c_occ::getOccHwmonDevices(DEV_PATH);
128 for (auto& name : deviceNames)
129 {
130 i2c_occ::i2cToDbus(name);
131 auto path = fs::path(OCC_CONTROL_ROOT) / name;
132 statusObjects.emplace_back(
133 std::make_unique<Status>(
134 bus,
135 event,
136 path.c_str()));
137 }
138}
139#endif
140
141} // namespace occ
142} // namespace open_power