blob: 2116d4961d07ddbcb476f712b5cd7ffdcf30d744 [file] [log] [blame]
Chris Cain5d66a0a2022-02-09 08:52:10 -06001#include "occ_status.hpp"
2
Chris Cain37abe9b2024-10-31 17:20:31 -05003#include <phosphor-logging/lg2.hpp>
Gunnar Mills94df8c92018-09-14 14:50:03 -05004#include <powercap.hpp>
George Liub5ca1012021-09-10 12:53:11 +08005
6#include <cassert>
Chris Caine2d0a432022-03-28 11:08:49 -05007#include <filesystem>
Andrew Geissler32016d12017-06-20 15:46:52 -05008
9namespace open_power
10{
11namespace occ
12{
13namespace powercap
14{
15
Gunnar Mills94df8c92018-09-14 14:50:03 -050016constexpr auto PCAP_PATH = "/xyz/openbmc_project/control/host0/power_cap";
Andrew Geissler52cf26a2017-07-06 12:56:32 -050017constexpr auto PCAP_INTERFACE = "xyz.openbmc_project.Control.Power.Cap";
18
Andrew Geissler52cf26a2017-07-06 12:56:32 -050019constexpr auto POWER_CAP_PROP = "PowerCap";
20constexpr auto POWER_CAP_ENABLE_PROP = "PowerCapEnable";
21
George Liubcef3b42021-09-10 12:39:02 +080022namespace fs = std::filesystem;
Andrew Geissler32016d12017-06-20 15:46:52 -050023
Chris Caind6ced7c2022-10-17 17:11:07 -050024using CapLimits =
25 sdbusplus::xyz::openbmc_project::Control::Power::server::CapLimits;
26
27// Print the current values
28void OccPersistCapData::print()
29{
30 if (capData.initialized)
31 {
32 lg2::info(
33 "OccPersistCapData: Soft Min: {SOFT}, Hard Min: {HARD}, Max: {MAX}",
34 "SOFT", capData.softMin, "HARD", capData.hardMin, "MAX",
35 capData.max);
36 }
37}
38
39// Saves the power cap data in the filesystem.
40void OccPersistCapData::save()
41{
42 std::filesystem::path opath =
43 std::filesystem::path{OCC_CONTROL_PERSIST_PATH} / powerCapFilename;
44
45 if (!std::filesystem::exists(opath.parent_path()))
46 {
47 std::filesystem::create_directory(opath.parent_path());
48 }
49
50 try
51 {
52 std::ofstream stream{opath.c_str(), std::ios_base::binary};
53 stream.write((char*)&capData, sizeof(capData));
54 }
55 catch (const std::exception& e)
56 {
57 auto error = errno;
58 lg2::error(
59 "OccPersistCapData::save: failed to read {PATH}, errno={ERRNO}, err={ERR}",
60 "PATH", opath, "ERRNO", error, "ERR", e);
61 capData.initialized = false;
62 }
63}
64
65// Loads the power cap data from the filesystem
66void OccPersistCapData::load()
67{
68 std::filesystem::path ipath =
69 std::filesystem::path{OCC_CONTROL_PERSIST_PATH} / powerCapFilename;
70
71 if (!std::filesystem::exists(ipath))
72 {
73 capData.initialized = false;
74 return;
75 }
76
77 try
78 {
79 PowerCapData newCapData;
80 std::ifstream stream{ipath.c_str(), std::ios_base::binary};
81 stream.read((char*)&newCapData, sizeof(newCapData));
Chris Cain03a8fe32024-12-10 14:46:20 -060082 if (newCapData.version == PCAPDATA_FILE_VERSION)
Chris Caind6ced7c2022-10-17 17:11:07 -050083 {
Chris Cain03a8fe32024-12-10 14:46:20 -060084 memcpy(&capData, &newCapData, sizeof(capData));
85 }
86 else
87 {
88 lg2::error(
Chris Caind6ced7c2022-10-17 17:11:07 -050089 "OccPersistCapData::load() file version was {VER} (expected {EXP})",
90 "VER", newCapData.version, "EXP", PCAPDATA_FILE_VERSION);
Chris Cain03a8fe32024-12-10 14:46:20 -060091 capData.initialized = false;
Chris Caind6ced7c2022-10-17 17:11:07 -050092 }
Chris Caind6ced7c2022-10-17 17:11:07 -050093 }
94 catch (const std::exception& e)
95 {
96 auto error = errno;
97 lg2::error(
98 "OccPersistCapData::load: failed to read {PATH}, errno={ERRNO}, err={ERR}",
99 "PATH", ipath, "ERRNO", error, "ERR", e);
100 capData.initialized = false;
101 }
102}
103
Chris Cain5d66a0a2022-02-09 08:52:10 -0600104void PowerCap::updatePcapBounds()
105{
106 // Build the hwmon string to write the power cap bounds
107 fs::path minName = getPcapFilename(std::regex{"power\\d+_cap_min$"});
Chris Cain613dc902022-04-08 09:56:22 -0500108 fs::path softMinName =
109 getPcapFilename(std::regex{"power\\d+_cap_min_soft$"});
Chris Cain5d66a0a2022-02-09 08:52:10 -0600110 fs::path maxName = getPcapFilename(std::regex{"power\\d+_cap_max$"});
111
Chris Caind6ced7c2022-10-17 17:11:07 -0500112 // Read the current limits from persistent data
Chris Cain81c83432022-06-27 08:21:52 -0500113 uint32_t capSoftMin, capHardMin, capMax;
Chris Caind6ced7c2022-10-17 17:11:07 -0500114 persistedData.getCapLimits(capSoftMin, capHardMin, capMax);
Chris Cain613dc902022-04-08 09:56:22 -0500115
Chris Cain81c83432022-06-27 08:21:52 -0500116 // Read the power cap bounds from sysfs files (from OCC)
117 uint64_t cap;
Chris Caind6ced7c2022-10-17 17:11:07 -0500118 bool parmsChanged = false;
Chris Cain613dc902022-04-08 09:56:22 -0500119 std::ifstream softMinFile(softMinName, std::ios::in);
120 if (softMinFile)
121 {
122 softMinFile >> cap;
123 softMinFile.close();
Chris Cain81c83432022-06-27 08:21:52 -0500124 // Convert to input/AC Power in Watts (round up)
Chris Cain613dc902022-04-08 09:56:22 -0500125 capSoftMin = ((cap / (PS_DERATING_FACTOR / 100.0) / 1000000) + 0.9);
Chris Caind6ced7c2022-10-17 17:11:07 -0500126 parmsChanged = true;
Chris Cain613dc902022-04-08 09:56:22 -0500127 }
128 else
129 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500130 lg2::error(
131 "updatePcapBounds: unable to find pcap_min_soft file: {FILE} (errno={ERR})",
132 "FILE", pcapBasePathname, "ERR", errno);
Chris Cain613dc902022-04-08 09:56:22 -0500133 }
134
Chris Cain5d66a0a2022-02-09 08:52:10 -0600135 std::ifstream minFile(minName, std::ios::in);
136 if (minFile)
137 {
138 minFile >> cap;
139 minFile.close();
Chris Cain81c83432022-06-27 08:21:52 -0500140 // Convert to input/AC Power in Watts (round up)
Chris Cain8676e032022-03-24 15:06:23 -0500141 capHardMin = ((cap / (PS_DERATING_FACTOR / 100.0) / 1000000) + 0.9);
Chris Caind6ced7c2022-10-17 17:11:07 -0500142 parmsChanged = true;
Chris Cain5d66a0a2022-02-09 08:52:10 -0600143 }
144 else
145 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500146 lg2::error(
147 "updatePcapBounds: unable to find cap_min file: {FILE} (errno={ERR})",
148 "FILE", pcapBasePathname, "ERR", errno);
Chris Cain5d66a0a2022-02-09 08:52:10 -0600149 }
Chris Cain613dc902022-04-08 09:56:22 -0500150
Chris Cain5d66a0a2022-02-09 08:52:10 -0600151 std::ifstream maxFile(maxName, std::ios::in);
152 if (maxFile)
153 {
154 maxFile >> cap;
155 maxFile.close();
Chris Cain81c83432022-06-27 08:21:52 -0500156 // Convert to input/AC Power in Watts (truncate remainder)
Chris Cain8676e032022-03-24 15:06:23 -0500157 capMax = cap / (PS_DERATING_FACTOR / 100.0) / 1000000;
Chris Caind6ced7c2022-10-17 17:11:07 -0500158 parmsChanged = true;
Chris Cain5d66a0a2022-02-09 08:52:10 -0600159 }
160 else
161 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500162 lg2::error(
163 "updatePcapBounds: unable to find cap_max file: {FILE} (errno={ERR})",
164 "FILE", pcapBasePathname, "ERR", errno);
Chris Cain5d66a0a2022-02-09 08:52:10 -0600165 }
166
Chris Caind6ced7c2022-10-17 17:11:07 -0500167 if (parmsChanged)
168 {
169 // Save the power cap bounds to dbus
170 updateDbusPcapLimits(capSoftMin, capHardMin, capMax);
171 persistedData.updateCapLimits(capSoftMin, capHardMin, capMax);
172 }
Chris Cain40501a22022-03-14 17:33:27 -0500173
Chris Cain81c83432022-06-27 08:21:52 -0500174 // Validate user power cap (if enabled) is within the bounds
Chris Cain40501a22022-03-14 17:33:27 -0500175 const uint32_t dbusUserCap = getPcap();
Chris Cain81c83432022-06-27 08:21:52 -0500176 const bool pcapEnabled = getPcapEnabled();
177 if (pcapEnabled && (dbusUserCap != 0))
Chris Cain40501a22022-03-14 17:33:27 -0500178 {
Chris Cain81c83432022-06-27 08:21:52 -0500179 const uint32_t hwmonUserCap = readUserCapHwmon();
180 if ((dbusUserCap >= capSoftMin) && (dbusUserCap <= capMax))
181 {
182 // Validate dbus and hwmon user caps match
183 if ((hwmonUserCap != 0) && (dbusUserCap != hwmonUserCap))
184 {
185 // User power cap is enabled, but does not match dbus
Chris Cain37abe9b2024-10-31 17:20:31 -0500186 lg2::error(
187 "updatePcapBounds: user powercap mismatch (hwmon:{HCAP}W, bdus:{DCAP}W) - using dbus",
188 "HCAP", hwmonUserCap, "DCAP", dbusUserCap);
Chris Cain81c83432022-06-27 08:21:52 -0500189 auto occInput = getOccInput(dbusUserCap, pcapEnabled);
190 writeOcc(occInput);
191 }
192 }
193 else
194 {
195 // User power cap is outside of current bounds
196 uint32_t newCap = capMax;
197 if (dbusUserCap < capSoftMin)
198 {
199 newCap = capSoftMin;
200 }
Chris Cain37abe9b2024-10-31 17:20:31 -0500201 lg2::error(
202 "updatePcapBounds: user powercap {CAP}W is outside bounds "
203 "(soft min:{SMIN}, min:{MIN}, max:{MAX})",
204 "CAP", dbusUserCap, "SMIN", capSoftMin, "MIN", capHardMin,
205 "MAX", capMax);
Chris Cain81c83432022-06-27 08:21:52 -0500206 try
207 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500208 lg2::info(
209 "updatePcapBounds: Updating user powercap from {OLD} to {NEW}W",
210 "OLD", hwmonUserCap, "NEW", newCap);
Chris Cain81c83432022-06-27 08:21:52 -0500211 utils::setProperty(PCAP_PATH, PCAP_INTERFACE, POWER_CAP_PROP,
212 newCap);
213 auto occInput = getOccInput(newCap, pcapEnabled);
214 writeOcc(occInput);
215 }
Patrick Williamsaf408082022-07-22 19:26:54 -0500216 catch (const sdbusplus::exception_t& e)
Chris Cain81c83432022-06-27 08:21:52 -0500217 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500218 lg2::error(
219 "updatePcapBounds: Failed to update user powercap due to {ERR}",
220 "ERR", e.what());
Chris Cain81c83432022-06-27 08:21:52 -0500221 }
222 }
Chris Cain40501a22022-03-14 17:33:27 -0500223 }
Chris Cain5d66a0a2022-02-09 08:52:10 -0600224}
225
Chris Cain81c83432022-06-27 08:21:52 -0500226// Get value of power cap to send to the OCC (output/DC power)
Andrew Geissler4cea4d22017-07-10 15:13:33 -0500227uint32_t PowerCap::getOccInput(uint32_t pcap, bool pcapEnabled)
228{
229 if (!pcapEnabled)
230 {
231 // Pcap disabled, return 0 to indicate disabled
232 return 0;
233 }
234
235 // If pcap is not disabled then just return the pcap with the derating
Chris Cain81c83432022-06-27 08:21:52 -0500236 // factor applied (output/DC power).
Gunnar Mills94df8c92018-09-14 14:50:03 -0500237 return ((static_cast<uint64_t>(pcap) * PS_DERATING_FACTOR) / 100);
Andrew Geissler4cea4d22017-07-10 15:13:33 -0500238}
239
Andrew Geissler52cf26a2017-07-06 12:56:32 -0500240uint32_t PowerCap::getPcap()
241{
George Liuf3b75142021-06-10 11:22:50 +0800242 utils::PropertyValue pcap{};
243 try
Andrew Geissler52cf26a2017-07-06 12:56:32 -0500244 {
George Liuf3b75142021-06-10 11:22:50 +0800245 pcap = utils::getProperty(PCAP_PATH, PCAP_INTERFACE, POWER_CAP_PROP);
246
247 return std::get<uint32_t>(pcap);
248 }
Patrick Williamsaf408082022-07-22 19:26:54 -0500249 catch (const sdbusplus::exception_t& e)
George Liuf3b75142021-06-10 11:22:50 +0800250 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500251 lg2::error("Failed to get PowerCap property: path={PATH}: {ERR}",
252 "PATH", PCAP_PATH, "ERR", e.what());
George Liuf3b75142021-06-10 11:22:50 +0800253
Andrew Geissler52cf26a2017-07-06 12:56:32 -0500254 return 0;
255 }
Andrew Geissler52cf26a2017-07-06 12:56:32 -0500256}
257
258bool PowerCap::getPcapEnabled()
259{
George Liuf3b75142021-06-10 11:22:50 +0800260 utils::PropertyValue pcapEnabled{};
261 try
Andrew Geissler52cf26a2017-07-06 12:56:32 -0500262 {
George Liuf3b75142021-06-10 11:22:50 +0800263 pcapEnabled = utils::getProperty(PCAP_PATH, PCAP_INTERFACE,
264 POWER_CAP_ENABLE_PROP);
Andrew Geissler52cf26a2017-07-06 12:56:32 -0500265
George Liuf3b75142021-06-10 11:22:50 +0800266 return std::get<bool>(pcapEnabled);
267 }
Patrick Williamsaf408082022-07-22 19:26:54 -0500268 catch (const sdbusplus::exception_t& e)
George Liuf3b75142021-06-10 11:22:50 +0800269 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500270 lg2::error("Failed to get PowerCapEnable property: path={PATH}: {ERR}",
271 "PATH", PCAP_PATH, "ERR", e.what());
George Liuf3b75142021-06-10 11:22:50 +0800272
273 return false;
274 }
Andrew Geissler52cf26a2017-07-06 12:56:32 -0500275}
Andrew Geissler32016d12017-06-20 15:46:52 -0500276
Chris Cain5d66a0a2022-02-09 08:52:10 -0600277fs::path PowerCap::getPcapFilename(const std::regex& expr)
Matt Spinlereaaf3b22019-07-16 10:29:27 -0500278{
Chris Cain5d66a0a2022-02-09 08:52:10 -0600279 if (pcapBasePathname.empty())
280 {
Chris Cain5d66a0a2022-02-09 08:52:10 -0600281 pcapBasePathname = occStatus.getHwmonPath();
Chris Cain5d66a0a2022-02-09 08:52:10 -0600282 }
Chris Caine2d0a432022-03-28 11:08:49 -0500283
284 if (fs::exists(pcapBasePathname))
Matt Spinlereaaf3b22019-07-16 10:29:27 -0500285 {
Chris Caine2d0a432022-03-28 11:08:49 -0500286 // Search for pcap file based on the supplied expr
287 for (auto& file : fs::directory_iterator(pcapBasePathname))
Matt Spinlereaaf3b22019-07-16 10:29:27 -0500288 {
Chris Caine2d0a432022-03-28 11:08:49 -0500289 if (std::regex_search(file.path().string(), expr))
290 {
291 // Found match
292 return file;
293 }
Matt Spinlereaaf3b22019-07-16 10:29:27 -0500294 }
295 }
Chris Caine2d0a432022-03-28 11:08:49 -0500296 else
297 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500298 lg2::error("Power Cap base filename not found: {FILE}", "FILE",
299 pcapBasePathname);
Chris Caine2d0a432022-03-28 11:08:49 -0500300 }
301
Chris Cain5d66a0a2022-02-09 08:52:10 -0600302 // return empty path
303 return fs::path{};
Matt Spinlereaaf3b22019-07-16 10:29:27 -0500304}
305
Chris Cain81c83432022-06-27 08:21:52 -0500306// Write the user power cap to sysfs (output/DC power)
Chris Cain40501a22022-03-14 17:33:27 -0500307// This will trigger the driver to send the cap to the OCC
Andrew Geissler6ac874e2017-07-10 15:54:58 -0500308void PowerCap::writeOcc(uint32_t pcapValue)
309{
Chris Caind4c19a02022-04-22 15:46:13 -0500310 if (!occStatus.occActive())
311 {
312 // OCC not running, skip update
313 return;
314 }
315
Chris Cain5d66a0a2022-02-09 08:52:10 -0600316 // Build the hwmon string to write the user power cap
317 fs::path fileName = getPcapFilename(std::regex{"power\\d+_cap_user$"});
318 if (fileName.empty())
Matt Spinlereaaf3b22019-07-16 10:29:27 -0500319 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500320 lg2::error("Could not find a power cap file to write to: {FILE})",
321 "FILE", pcapBasePathname);
Matt Spinlereaaf3b22019-07-16 10:29:27 -0500322 return;
323 }
Matt Spinlereaaf3b22019-07-16 10:29:27 -0500324
325 uint64_t microWatts = pcapValue * 1000000ull;
326
327 auto pcapString{std::to_string(microWatts)};
Andrew Geissler6ac874e2017-07-10 15:54:58 -0500328
Andrew Geissler6ac874e2017-07-10 15:54:58 -0500329 // Open the hwmon file and write the power cap
Chris Cain5d66a0a2022-02-09 08:52:10 -0600330 std::ofstream file(fileName, std::ios::out);
331 if (file)
332 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500333 lg2::info("Writing {CAP}uW to {FILE}", "CAP", pcapString, "FILE",
334 fileName);
Chris Cain5d66a0a2022-02-09 08:52:10 -0600335 file << pcapString;
336 file.close();
337 }
338 else
339 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500340 lg2::error("Failed writing {CAP}uW to {FILE} (errno={ERR})", "CAP",
341 microWatts, "FILE", fileName, "ERR", errno);
Chris Cain5d66a0a2022-02-09 08:52:10 -0600342 }
343
Andrew Geissler6ac874e2017-07-10 15:54:58 -0500344 return;
345}
346
Chris Cain81c83432022-06-27 08:21:52 -0500347// Read the current user power cap from sysfs as input/AC power
Chris Cain40501a22022-03-14 17:33:27 -0500348uint32_t PowerCap::readUserCapHwmon()
349{
350 uint32_t userCap = 0;
351
352 // Get the sysfs filename for the user power cap
353 fs::path userCapName = getPcapFilename(std::regex{"power\\d+_cap_user$"});
354 if (userCapName.empty())
355 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500356 lg2::error(
357 "readUserCapHwmon: Could not find a power cap file to read: {FILE})",
358 "FILE", pcapBasePathname);
Chris Cain40501a22022-03-14 17:33:27 -0500359 return 0;
360 }
361
362 // Open the sysfs file and read the power cap
Chris Cain40501a22022-03-14 17:33:27 -0500363 std::ifstream file(userCapName, std::ios::in);
364 if (file)
365 {
Chris Caine2d0a432022-03-28 11:08:49 -0500366 uint64_t cap;
Chris Cain40501a22022-03-14 17:33:27 -0500367 file >> cap;
368 file.close();
Chris Cain81c83432022-06-27 08:21:52 -0500369 // Convert to input/AC Power in Watts
370 userCap = (cap / (PS_DERATING_FACTOR / 100.0) / 1000000);
Chris Cain40501a22022-03-14 17:33:27 -0500371 }
372 else
373 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500374 lg2::error("readUserCapHwmon: Failed reading {FILE} (errno={ERR})",
375 "FILE", userCapName, "ERR", errno);
Chris Cain40501a22022-03-14 17:33:27 -0500376 }
377
378 return userCap;
379}
380
Patrick Williamsaf408082022-07-22 19:26:54 -0500381void PowerCap::pcapChanged(sdbusplus::message_t& msg)
Andrew Geissler32016d12017-06-20 15:46:52 -0500382{
Andrew Geissler32016d12017-06-20 15:46:52 -0500383 if (!occStatus.occActive())
384 {
Chris Cain5d66a0a2022-02-09 08:52:10 -0600385 // Nothing to do
Andrew Geissler32016d12017-06-20 15:46:52 -0500386 return;
387 }
Andrew Geissler52cf26a2017-07-06 12:56:32 -0500388
389 uint32_t pcap = 0;
390 bool pcapEnabled = false;
391
392 std::string msgSensor;
Patrick Williamse0962702020-05-13 17:50:22 -0500393 std::map<std::string, std::variant<uint32_t, bool>> msgData;
Andrew Geissler52cf26a2017-07-06 12:56:32 -0500394 msg.read(msgSensor, msgData);
395
Chris Cain5d66a0a2022-02-09 08:52:10 -0600396 bool changeFound = false;
397 for (const auto& [prop, value] : msgData)
Andrew Geissler52cf26a2017-07-06 12:56:32 -0500398 {
Chris Cain5d66a0a2022-02-09 08:52:10 -0600399 if (prop == POWER_CAP_PROP)
Andrew Geissler52cf26a2017-07-06 12:56:32 -0500400 {
Chris Cain5d66a0a2022-02-09 08:52:10 -0600401 pcap = std::get<uint32_t>(value);
402 pcapEnabled = getPcapEnabled();
403 changeFound = true;
404 }
405 else if (prop == POWER_CAP_ENABLE_PROP)
406 {
407 pcapEnabled = std::get<bool>(value);
Andrew Geissler52cf26a2017-07-06 12:56:32 -0500408 pcap = getPcap();
Chris Cain5d66a0a2022-02-09 08:52:10 -0600409 changeFound = true;
Andrew Geissler52cf26a2017-07-06 12:56:32 -0500410 }
411 else
412 {
Chris Cain5d66a0a2022-02-09 08:52:10 -0600413 // Ignore other properties
Chris Cain37abe9b2024-10-31 17:20:31 -0500414 lg2::debug(
415 "pcapChanged: Unknown power cap property changed {PROP} to {VAL}",
416 "PROP", prop, "VAL", std::get<uint32_t>(value));
Andrew Geissler52cf26a2017-07-06 12:56:32 -0500417 }
418 }
419
Chris Cain81c83432022-06-27 08:21:52 -0500420 // Validate the cap is within supported range
421 uint32_t capSoftMin, capHardMin, capMax;
Chris Caind6ced7c2022-10-17 17:11:07 -0500422 persistedData.getCapLimits(capSoftMin, capHardMin, capMax);
Chris Cain81c83432022-06-27 08:21:52 -0500423 if (((pcap > 0) && (pcap < capSoftMin)) || ((pcap == 0) && (pcapEnabled)))
424 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500425 lg2::error(
426 "pcapChanged: Power cap of {CAP}W is lower than allowed (soft min:{SMIN}, min:{MIN}) - using soft min",
427 "CAP", pcap, "SMIN", capSoftMin, "MIN", capHardMin);
Chris Cain81c83432022-06-27 08:21:52 -0500428 pcap = capSoftMin;
429 utils::setProperty(PCAP_PATH, PCAP_INTERFACE, POWER_CAP_PROP, pcap);
430 }
431 else if (pcap > capMax)
432 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500433 lg2::error(
434 "pcapChanged: Power cap of {CAP}W is higher than allowed (max:{MAX}) - using max",
435 "CAP", pcap, "MAX", capMax);
Chris Cain81c83432022-06-27 08:21:52 -0500436 pcap = capMax;
437 utils::setProperty(PCAP_PATH, PCAP_INTERFACE, POWER_CAP_PROP, pcap);
438 }
439
Chris Cain5d66a0a2022-02-09 08:52:10 -0600440 if (changeFound)
441 {
Chris Cain37abe9b2024-10-31 17:20:31 -0500442 lg2::info(
443 "Power Cap Property Change (cap={CAP}W (input), enabled={ENABLE})",
444 "CAP", pcap, "ENABLE", pcapEnabled);
Andrew Geissler52cf26a2017-07-06 12:56:32 -0500445
Chris Cain5d66a0a2022-02-09 08:52:10 -0600446 // Determine desired action to write to occ
Chris Cain5d66a0a2022-02-09 08:52:10 -0600447 auto occInput = getOccInput(pcap, pcapEnabled);
Chris Cain5d66a0a2022-02-09 08:52:10 -0600448 // Write action to occ
449 writeOcc(occInput);
450 }
Andrew Geissler52cf26a2017-07-06 12:56:32 -0500451
452 return;
Andrew Geissler32016d12017-06-20 15:46:52 -0500453}
454
Chris Cain5d66a0a2022-02-09 08:52:10 -0600455// Update the Power Cap bounds on DBus
Chris Caind6ced7c2022-10-17 17:11:07 -0500456void PowerCap::updateDbusPcapLimits(uint32_t softMin, uint32_t hardMin,
Chris Cain81c83432022-06-27 08:21:52 -0500457 uint32_t max)
Chris Cain5d66a0a2022-02-09 08:52:10 -0600458{
Chris Caind6ced7c2022-10-17 17:11:07 -0500459 CapLimits::minSoftPowerCapValue(softMin);
460 CapLimits::minPowerCapValue(hardMin);
461 CapLimits::maxPowerCapValue(max);
Chris Cain81c83432022-06-27 08:21:52 -0500462}
463
Gunnar Mills94df8c92018-09-14 14:50:03 -0500464} // namespace powercap
Andrew Geissler32016d12017-06-20 15:46:52 -0500465
466} // namespace occ
467
Gunnar Mills94df8c92018-09-14 14:50:03 -0500468} // namespace open_power