blob: fc9a112abbadb652e99ae10939b3bbd73dc75d87 [file] [log] [blame]
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +05301#include "config.h"
2
Gunnar Mills94df8c92018-09-14 14:50:03 -05003#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
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +053014namespace open_power
15{
16namespace occ
17{
18
Chris Caina8857c52021-01-27 11:53:05 -060019using namespace phosphor::logging;
20
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +053021void Manager::findAndCreateObjects()
22{
Deepak Kodihalli370f06b2017-10-25 04:26:07 -050023 for (auto id = 0; id < MAX_CPUS; ++id)
24 {
Deepak Kodihalli30417a12017-12-04 00:54:01 -060025 // Create one occ per cpu
26 auto occ = std::string(OCC_NAME) + std::to_string(id);
27 createObjects(occ);
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +053028 }
29}
30
31int Manager::cpuCreated(sdbusplus::message::message& msg)
32{
33 namespace fs = std::experimental::filesystem;
34
35 sdbusplus::message::object_path o;
36 msg.read(o);
37 fs::path cpuPath(std::string(std::move(o)));
38
39 auto name = cpuPath.filename().string();
40 auto index = name.find(CPU_NAME);
41 name.replace(index, std::strlen(CPU_NAME), OCC_NAME);
42
43 createObjects(name);
44
45 return 0;
46}
47
48void Manager::createObjects(const std::string& occ)
49{
50 auto path = fs::path(OCC_CONTROL_ROOT) / occ;
51
52 passThroughObjects.emplace_back(
Gunnar Mills94df8c92018-09-14 14:50:03 -050053 std::make_unique<PassThrough>(bus, path.c_str()));
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +053054
Gunnar Mills94df8c92018-09-14 14:50:03 -050055 statusObjects.emplace_back(std::make_unique<Status>(
56 bus, event, path.c_str(), *this,
57 std::bind(std::mem_fn(&Manager::statusCallBack), this,
Tom Joseph00325232020-07-29 17:51:48 +053058 std::placeholders::_1)
59#ifdef PLDM
60 ,
61 std::bind(std::mem_fn(&pldm::Interface::resetOCC), pldmHandle.get(),
62 std::placeholders::_1)
63#endif
64 ));
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +053065
66 // Create the power cap monitor object for master occ (0)
67 if (!pcap)
68 {
69 pcap = std::make_unique<open_power::occ::powercap::PowerCap>(
Gunnar Mills94df8c92018-09-14 14:50:03 -050070 bus, *statusObjects.front());
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +053071 }
72}
73
74void Manager::statusCallBack(bool status)
75{
Gunnar Mills94df8c92018-09-14 14:50:03 -050076 using InternalFailure =
77 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +053078
79 // At this time, it won't happen but keeping it
80 // here just in case something changes in the future
81 if ((activeCount == 0) && (!status))
82 {
83 log<level::ERR>("Invalid update on OCCActive");
84 elog<InternalFailure>();
85 }
86
87 activeCount += status ? 1 : -1;
Eddie Jamesdae2d942017-12-20 10:50:03 -060088
89 // Only start presence detection if all the OCCs are bound
90 if (activeCount == statusObjects.size())
91 {
Gunnar Mills94df8c92018-09-14 14:50:03 -050092 for (auto& obj : statusObjects)
Eddie Jamesdae2d942017-12-20 10:50:03 -060093 {
94 obj->addPresenceWatchMaster();
95 }
96 }
Chris Caina8857c52021-01-27 11:53:05 -060097
98 if ((!_pollTimer->isEnabled()) && (activeCount > 0))
99 {
100 log<level::INFO>(fmt::format("Manager::statusCallBack(): {} OCCs will "
101 "be polled every {} seconds",
102 activeCount, pollInterval)
103 .c_str());
104
105 // Send poll and start OCC poll timer
106 pollerTimerExpired();
107 }
108 else if ((_pollTimer->isEnabled()) && (activeCount == 0))
109 {
110 // Stop OCC poll timer
111 log<level::INFO>("Manager::statusCallBack(): OCCs are not running, "
112 "stopping poll timer");
113 _pollTimer->setEnabled(false);
114 }
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +0530115}
116
117#ifdef I2C_OCC
118void Manager::initStatusObjects()
119{
120 // Make sure we have a valid path string
121 static_assert(sizeof(DEV_PATH) != 0);
122
123 auto deviceNames = i2c_occ::getOccHwmonDevices(DEV_PATH);
Lei YU41470e52017-11-30 16:03:50 +0800124 auto occMasterName = deviceNames.front();
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +0530125 for (auto& name : deviceNames)
126 {
127 i2c_occ::i2cToDbus(name);
Lei YUb5259a12017-09-01 16:22:40 +0800128 name = std::string(OCC_NAME) + '_' + name;
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +0530129 auto path = fs::path(OCC_CONTROL_ROOT) / name;
130 statusObjects.emplace_back(
Gunnar Mills94df8c92018-09-14 14:50:03 -0500131 std::make_unique<Status>(bus, event, path.c_str(), *this));
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +0530132 }
Lei YU41470e52017-11-30 16:03:50 +0800133 // The first device is master occ
134 pcap = std::make_unique<open_power::occ::powercap::PowerCap>(
Gunnar Mills94df8c92018-09-14 14:50:03 -0500135 bus, *statusObjects.front(), occMasterName);
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +0530136}
137#endif
138
Tom Joseph815f9f52020-07-27 12:12:13 +0530139#ifdef PLDM
140bool Manager::updateOCCActive(instanceID instance, bool status)
141{
142 return (statusObjects[instance])->occActive(status);
143}
144#endif
145
Chris Caina8857c52021-01-27 11:53:05 -0600146void Manager::pollerTimerExpired()
147{
148 if (activeCount == 0)
149 {
150 // No OCCs running, so poll timer will not be restarted
151 log<level::INFO>("Manager::pollerTimerExpire(): No OCCs running, poll "
152 "timer not restarted");
153 }
154
155 if (!_pollTimer)
156 {
157 log<level::ERR>(
158 "Manager::pollerTimerExpired() ERROR: Timer not defined");
159 return;
160 }
161
162 for (auto& obj : statusObjects)
163 {
164 // Read sysfs to force kernel to poll OCC
165 obj->readOccState();
166 }
167
168 // Restart OCC poll timer
169 _pollTimer->restartOnce(std::chrono::seconds(pollInterval));
170}
171
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +0530172} // namespace occ
173} // namespace open_power