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