blob: 3ebd90ae09cc99febb53217c676fbdddc5781987 [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"
Gunnar Mills94df8c92018-09-14 14:50:03 -05006#include "utils.hpp"
7
8#include <experimental/filesystem>
9#include <phosphor-logging/elog-errors.hpp>
10#include <phosphor-logging/log.hpp>
11#include <xyz/openbmc_project/Common/error.hpp>
12
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +053013namespace open_power
14{
15namespace occ
16{
17
Chris Caina8857c52021-01-27 11:53:05 -060018using namespace phosphor::logging;
19
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +053020void Manager::findAndCreateObjects()
21{
Deepak Kodihalli370f06b2017-10-25 04:26:07 -050022 for (auto id = 0; id < MAX_CPUS; ++id)
23 {
Deepak Kodihalli30417a12017-12-04 00:54:01 -060024 // Create one occ per cpu
25 auto occ = std::string(OCC_NAME) + std::to_string(id);
26 createObjects(occ);
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +053027 }
28}
29
30int Manager::cpuCreated(sdbusplus::message::message& msg)
31{
32 namespace fs = std::experimental::filesystem;
33
34 sdbusplus::message::object_path o;
35 msg.read(o);
36 fs::path cpuPath(std::string(std::move(o)));
37
38 auto name = cpuPath.filename().string();
39 auto index = name.find(CPU_NAME);
40 name.replace(index, std::strlen(CPU_NAME), OCC_NAME);
41
42 createObjects(name);
43
44 return 0;
45}
46
47void Manager::createObjects(const std::string& occ)
48{
49 auto path = fs::path(OCC_CONTROL_ROOT) / occ;
50
51 passThroughObjects.emplace_back(
George Liuf3b75142021-06-10 11:22:50 +080052 std::make_unique<PassThrough>(path.c_str()));
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +053053
Gunnar Mills94df8c92018-09-14 14:50:03 -050054 statusObjects.emplace_back(std::make_unique<Status>(
George Liuf3b75142021-06-10 11:22:50 +080055 event, path.c_str(), *this,
Gunnar Mills94df8c92018-09-14 14:50:03 -050056 std::bind(std::mem_fn(&Manager::statusCallBack), this,
Tom Joseph00325232020-07-29 17:51:48 +053057 std::placeholders::_1)
58#ifdef PLDM
59 ,
60 std::bind(std::mem_fn(&pldm::Interface::resetOCC), pldmHandle.get(),
61 std::placeholders::_1)
62#endif
63 ));
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +053064
65 // Create the power cap monitor object for master occ (0)
66 if (!pcap)
67 {
68 pcap = std::make_unique<open_power::occ::powercap::PowerCap>(
George Liuf3b75142021-06-10 11:22:50 +080069 *statusObjects.front());
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +053070 }
Chris Cain78e86012021-03-04 16:15:31 -060071
72#ifdef POWER10
73 // Create the power mode monitor object for master occ (0)
74 if (!pmode)
75 {
76 pmode = std::make_unique<open_power::occ::powermode::PowerMode>(
77 *statusObjects.front());
78 }
79#endif
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +053080}
81
82void Manager::statusCallBack(bool status)
83{
Gunnar Mills94df8c92018-09-14 14:50:03 -050084 using InternalFailure =
85 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +053086
87 // At this time, it won't happen but keeping it
88 // here just in case something changes in the future
89 if ((activeCount == 0) && (!status))
90 {
91 log<level::ERR>("Invalid update on OCCActive");
92 elog<InternalFailure>();
93 }
94
95 activeCount += status ? 1 : -1;
Eddie Jamesdae2d942017-12-20 10:50:03 -060096
97 // Only start presence detection if all the OCCs are bound
98 if (activeCount == statusObjects.size())
99 {
Gunnar Mills94df8c92018-09-14 14:50:03 -0500100 for (auto& obj : statusObjects)
Eddie Jamesdae2d942017-12-20 10:50:03 -0600101 {
102 obj->addPresenceWatchMaster();
103 }
104 }
Chris Caina8857c52021-01-27 11:53:05 -0600105
106 if ((!_pollTimer->isEnabled()) && (activeCount > 0))
107 {
108 log<level::INFO>(fmt::format("Manager::statusCallBack(): {} OCCs will "
109 "be polled every {} seconds",
110 activeCount, pollInterval)
111 .c_str());
112
113 // Send poll and start OCC poll timer
114 pollerTimerExpired();
115 }
116 else if ((_pollTimer->isEnabled()) && (activeCount == 0))
117 {
118 // Stop OCC poll timer
119 log<level::INFO>("Manager::statusCallBack(): OCCs are not running, "
120 "stopping poll timer");
121 _pollTimer->setEnabled(false);
122 }
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +0530123}
124
125#ifdef I2C_OCC
126void Manager::initStatusObjects()
127{
128 // Make sure we have a valid path string
129 static_assert(sizeof(DEV_PATH) != 0);
130
131 auto deviceNames = i2c_occ::getOccHwmonDevices(DEV_PATH);
Lei YU41470e52017-11-30 16:03:50 +0800132 auto occMasterName = deviceNames.front();
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +0530133 for (auto& name : deviceNames)
134 {
135 i2c_occ::i2cToDbus(name);
Lei YUb5259a12017-09-01 16:22:40 +0800136 name = std::string(OCC_NAME) + '_' + name;
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +0530137 auto path = fs::path(OCC_CONTROL_ROOT) / name;
138 statusObjects.emplace_back(
George Liuf3b75142021-06-10 11:22:50 +0800139 std::make_unique<Status>(event, path.c_str(), *this));
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +0530140 }
Lei YU41470e52017-11-30 16:03:50 +0800141 // The first device is master occ
142 pcap = std::make_unique<open_power::occ::powercap::PowerCap>(
George Liuf3b75142021-06-10 11:22:50 +0800143 *statusObjects.front(), occMasterName);
Chris Cain78e86012021-03-04 16:15:31 -0600144#ifdef POWER10
145 pmode = std::make_unique<open_power::occ::powermode::PowerMode>(
146 *statusObjects.front());
147#endif
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +0530148}
149#endif
150
Tom Joseph815f9f52020-07-27 12:12:13 +0530151#ifdef PLDM
152bool Manager::updateOCCActive(instanceID instance, bool status)
153{
154 return (statusObjects[instance])->occActive(status);
155}
156#endif
157
Chris Caina8857c52021-01-27 11:53:05 -0600158void Manager::pollerTimerExpired()
159{
160 if (activeCount == 0)
161 {
162 // No OCCs running, so poll timer will not be restarted
163 log<level::INFO>("Manager::pollerTimerExpire(): No OCCs running, poll "
164 "timer not restarted");
165 }
166
167 if (!_pollTimer)
168 {
169 log<level::ERR>(
170 "Manager::pollerTimerExpired() ERROR: Timer not defined");
171 return;
172 }
173
174 for (auto& obj : statusObjects)
175 {
176 // Read sysfs to force kernel to poll OCC
177 obj->readOccState();
178 }
179
180 // Restart OCC poll timer
181 _pollTimer->restartOnce(std::chrono::seconds(pollInterval));
182}
183
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +0530184} // namespace occ
185} // namespace open_power