blob: 4b209da620f21bdf82ede5e473d50bdc2f732095 [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 }
71}
72
73void Manager::statusCallBack(bool status)
74{
Gunnar Mills94df8c92018-09-14 14:50:03 -050075 using InternalFailure =
76 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +053077
78 // At this time, it won't happen but keeping it
79 // here just in case something changes in the future
80 if ((activeCount == 0) && (!status))
81 {
82 log<level::ERR>("Invalid update on OCCActive");
83 elog<InternalFailure>();
84 }
85
86 activeCount += status ? 1 : -1;
Eddie Jamesdae2d942017-12-20 10:50:03 -060087
88 // Only start presence detection if all the OCCs are bound
89 if (activeCount == statusObjects.size())
90 {
Gunnar Mills94df8c92018-09-14 14:50:03 -050091 for (auto& obj : statusObjects)
Eddie Jamesdae2d942017-12-20 10:50:03 -060092 {
93 obj->addPresenceWatchMaster();
94 }
95 }
Chris Caina8857c52021-01-27 11:53:05 -060096
97 if ((!_pollTimer->isEnabled()) && (activeCount > 0))
98 {
99 log<level::INFO>(fmt::format("Manager::statusCallBack(): {} OCCs will "
100 "be polled every {} seconds",
101 activeCount, pollInterval)
102 .c_str());
103
104 // Send poll and start OCC poll timer
105 pollerTimerExpired();
106 }
107 else if ((_pollTimer->isEnabled()) && (activeCount == 0))
108 {
109 // Stop OCC poll timer
110 log<level::INFO>("Manager::statusCallBack(): OCCs are not running, "
111 "stopping poll timer");
112 _pollTimer->setEnabled(false);
113 }
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +0530114}
115
116#ifdef I2C_OCC
117void Manager::initStatusObjects()
118{
119 // Make sure we have a valid path string
120 static_assert(sizeof(DEV_PATH) != 0);
121
122 auto deviceNames = i2c_occ::getOccHwmonDevices(DEV_PATH);
Lei YU41470e52017-11-30 16:03:50 +0800123 auto occMasterName = deviceNames.front();
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +0530124 for (auto& name : deviceNames)
125 {
126 i2c_occ::i2cToDbus(name);
Lei YUb5259a12017-09-01 16:22:40 +0800127 name = std::string(OCC_NAME) + '_' + name;
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +0530128 auto path = fs::path(OCC_CONTROL_ROOT) / name;
129 statusObjects.emplace_back(
George Liuf3b75142021-06-10 11:22:50 +0800130 std::make_unique<Status>(event, path.c_str(), *this));
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +0530131 }
Lei YU41470e52017-11-30 16:03:50 +0800132 // The first device is master occ
133 pcap = std::make_unique<open_power::occ::powercap::PowerCap>(
George Liuf3b75142021-06-10 11:22:50 +0800134 *statusObjects.front(), occMasterName);
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +0530135}
136#endif
137
Tom Joseph815f9f52020-07-27 12:12:13 +0530138#ifdef PLDM
139bool Manager::updateOCCActive(instanceID instance, bool status)
140{
141 return (statusObjects[instance])->occActive(status);
142}
143#endif
144
Chris Caina8857c52021-01-27 11:53:05 -0600145void Manager::pollerTimerExpired()
146{
147 if (activeCount == 0)
148 {
149 // No OCCs running, so poll timer will not be restarted
150 log<level::INFO>("Manager::pollerTimerExpire(): No OCCs running, poll "
151 "timer not restarted");
152 }
153
154 if (!_pollTimer)
155 {
156 log<level::ERR>(
157 "Manager::pollerTimerExpired() ERROR: Timer not defined");
158 return;
159 }
160
161 for (auto& obj : statusObjects)
162 {
163 // Read sysfs to force kernel to poll OCC
164 obj->readOccState();
165 }
166
167 // Restart OCC poll timer
168 _pollTimer->restartOnce(std::chrono::seconds(pollInterval));
169}
170
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +0530171} // namespace occ
172} // namespace open_power