15d66a0aaSChris Cain #include "occ_status.hpp"
25d66a0aaSChris Cain 
332016d18SAndrew Geissler #include <phosphor-logging/log.hpp>
494df8c90SGunnar Mills #include <powercap.hpp>
5b5ca1015SGeorge Liu 
6b5ca1015SGeorge Liu #include <cassert>
7e2d0a43cSChris Cain #include <filesystem>
848002498SPatrick Williams #include <format>
932016d18SAndrew Geissler 
1032016d18SAndrew Geissler namespace open_power
1132016d18SAndrew Geissler {
1232016d18SAndrew Geissler namespace occ
1332016d18SAndrew Geissler {
1432016d18SAndrew Geissler namespace powercap
1532016d18SAndrew Geissler {
1632016d18SAndrew Geissler 
1752cf26a8SAndrew Geissler constexpr auto PCAP_PATH = "/xyz/openbmc_project/control/host0/power_cap";
1852cf26a8SAndrew Geissler constexpr auto PCAP_INTERFACE = "xyz.openbmc_project.Control.Power.Cap";
1952cf26a8SAndrew Geissler 
2052cf26a8SAndrew Geissler constexpr auto POWER_CAP_PROP = "PowerCap";
2152cf26a8SAndrew Geissler constexpr auto POWER_CAP_ENABLE_PROP = "PowerCapEnable";
22613dc90dSChris Cain constexpr auto POWER_CAP_SOFT_MIN = "MinSoftPowerCapValue";
235d66a0aaSChris Cain constexpr auto POWER_CAP_HARD_MIN = "MinPowerCapValue";
245d66a0aaSChris Cain constexpr auto POWER_CAP_MAX = "MaxPowerCapValue";
2552cf26a8SAndrew Geissler 
2632016d18SAndrew Geissler using namespace phosphor::logging;
27bcef3b48SGeorge Liu namespace fs = std::filesystem;
2832016d18SAndrew Geissler 
updatePcapBounds()295d66a0aaSChris Cain void PowerCap::updatePcapBounds()
305d66a0aaSChris Cain {
315d66a0aaSChris Cain     // Build the hwmon string to write the power cap bounds
325d66a0aaSChris Cain     fs::path minName = getPcapFilename(std::regex{"power\\d+_cap_min$"});
33613dc90dSChris Cain     fs::path softMinName =
34613dc90dSChris Cain         getPcapFilename(std::regex{"power\\d+_cap_min_soft$"});
355d66a0aaSChris Cain     fs::path maxName = getPcapFilename(std::regex{"power\\d+_cap_max$"});
365d66a0aaSChris Cain 
3781c83430SChris Cain     // Read the current cap bounds from dbus
3881c83430SChris Cain     uint32_t capSoftMin, capHardMin, capMax;
3981c83430SChris Cain     readDbusPcapLimits(capSoftMin, capHardMin, capMax);
40613dc90dSChris Cain 
4181c83430SChris Cain     // Read the power cap bounds from sysfs files (from OCC)
4281c83430SChris Cain     uint64_t cap;
43613dc90dSChris Cain     std::ifstream softMinFile(softMinName, std::ios::in);
44613dc90dSChris Cain     if (softMinFile)
45613dc90dSChris Cain     {
46613dc90dSChris Cain         softMinFile >> cap;
47613dc90dSChris Cain         softMinFile.close();
4881c83430SChris Cain         // Convert to input/AC Power in Watts (round up)
49613dc90dSChris Cain         capSoftMin = ((cap / (PS_DERATING_FACTOR / 100.0) / 1000000) + 0.9);
50613dc90dSChris Cain     }
51613dc90dSChris Cain     else
52613dc90dSChris Cain     {
53613dc90dSChris Cain         log<level::ERR>(
5448002498SPatrick Williams             std::format(
55613dc90dSChris Cain                 "updatePcapBounds: unable to find pcap_min_soft file: {} (errno={})",
56613dc90dSChris Cain                 pcapBasePathname.c_str(), errno)
57613dc90dSChris Cain                 .c_str());
58613dc90dSChris Cain     }
59613dc90dSChris Cain 
605d66a0aaSChris Cain     std::ifstream minFile(minName, std::ios::in);
615d66a0aaSChris Cain     if (minFile)
625d66a0aaSChris Cain     {
635d66a0aaSChris Cain         minFile >> cap;
645d66a0aaSChris Cain         minFile.close();
6581c83430SChris Cain         // Convert to input/AC Power in Watts (round up)
668676e037SChris Cain         capHardMin = ((cap / (PS_DERATING_FACTOR / 100.0) / 1000000) + 0.9);
675d66a0aaSChris Cain     }
685d66a0aaSChris Cain     else
695d66a0aaSChris Cain     {
705d66a0aaSChris Cain         log<level::ERR>(
7148002498SPatrick Williams             std::format(
725d66a0aaSChris Cain                 "updatePcapBounds: unable to find cap_min file: {} (errno={})",
735d66a0aaSChris Cain                 pcapBasePathname.c_str(), errno)
745d66a0aaSChris Cain                 .c_str());
755d66a0aaSChris Cain     }
76613dc90dSChris Cain 
775d66a0aaSChris Cain     std::ifstream maxFile(maxName, std::ios::in);
785d66a0aaSChris Cain     if (maxFile)
795d66a0aaSChris Cain     {
805d66a0aaSChris Cain         maxFile >> cap;
815d66a0aaSChris Cain         maxFile.close();
8281c83430SChris Cain         // Convert to input/AC Power in Watts (truncate remainder)
838676e037SChris Cain         capMax = cap / (PS_DERATING_FACTOR / 100.0) / 1000000;
845d66a0aaSChris Cain     }
855d66a0aaSChris Cain     else
865d66a0aaSChris Cain     {
875d66a0aaSChris Cain         log<level::ERR>(
8848002498SPatrick Williams             std::format(
895d66a0aaSChris Cain                 "updatePcapBounds: unable to find cap_max file: {} (errno={})",
905d66a0aaSChris Cain                 pcapBasePathname.c_str(), errno)
915d66a0aaSChris Cain                 .c_str());
925d66a0aaSChris Cain     }
935d66a0aaSChris Cain 
9481c83430SChris Cain     // Save the power cap bounds to dbus
9581c83430SChris Cain     updateDbusPcapLimits(capSoftMin, capHardMin, capMax);
9640501a23SChris Cain 
9781c83430SChris Cain     // Validate user power cap (if enabled) is within the bounds
9840501a23SChris Cain     const uint32_t dbusUserCap = getPcap();
9981c83430SChris Cain     const bool pcapEnabled = getPcapEnabled();
10081c83430SChris Cain     if (pcapEnabled && (dbusUserCap != 0))
10181c83430SChris Cain     {
10240501a23SChris Cain         const uint32_t hwmonUserCap = readUserCapHwmon();
10381c83430SChris Cain         if ((dbusUserCap >= capSoftMin) && (dbusUserCap <= capMax))
10481c83430SChris Cain         {
10581c83430SChris Cain             // Validate dbus and hwmon user caps match
10640501a23SChris Cain             if ((hwmonUserCap != 0) && (dbusUserCap != hwmonUserCap))
10740501a23SChris Cain             {
10840501a23SChris Cain                 // User power cap is enabled, but does not match dbus
10940501a23SChris Cain                 log<level::ERR>(
11048002498SPatrick Williams                     std::format(
11140501a23SChris Cain                         "updatePcapBounds: user powercap mismatch (hwmon:{}W, bdus:{}W) - using dbus",
11240501a23SChris Cain                         hwmonUserCap, dbusUserCap)
11340501a23SChris Cain                         .c_str());
11481c83430SChris Cain                 auto occInput = getOccInput(dbusUserCap, pcapEnabled);
11581c83430SChris Cain                 writeOcc(occInput);
11681c83430SChris Cain             }
11781c83430SChris Cain         }
11881c83430SChris Cain         else
11981c83430SChris Cain         {
12081c83430SChris Cain             // User power cap is outside of current bounds
12181c83430SChris Cain             uint32_t newCap = capMax;
12281c83430SChris Cain             if (dbusUserCap < capSoftMin)
12381c83430SChris Cain             {
12481c83430SChris Cain                 newCap = capSoftMin;
12581c83430SChris Cain             }
12681c83430SChris Cain             log<level::ERR>(
12748002498SPatrick Williams                 std::format(
12881c83430SChris Cain                     "updatePcapBounds: user powercap {}W is outside bounds "
12981c83430SChris Cain                     "(soft min:{}, min:{}, max:{})",
13081c83430SChris Cain                     dbusUserCap, capSoftMin, capHardMin, capMax)
13181c83430SChris Cain                     .c_str());
13281c83430SChris Cain             try
13381c83430SChris Cain             {
13481c83430SChris Cain                 log<level::INFO>(
13548002498SPatrick Williams                     std::format(
13681c83430SChris Cain                         "updatePcapBounds: Updating user powercap from {} to {}W",
13781c83430SChris Cain                         hwmonUserCap, newCap)
13881c83430SChris Cain                         .c_str());
13981c83430SChris Cain                 utils::setProperty(PCAP_PATH, PCAP_INTERFACE, POWER_CAP_PROP,
14081c83430SChris Cain                                    newCap);
14181c83430SChris Cain                 auto occInput = getOccInput(newCap, pcapEnabled);
14281c83430SChris Cain                 writeOcc(occInput);
14381c83430SChris Cain             }
144af40808fSPatrick Williams             catch (const sdbusplus::exception_t& e)
14581c83430SChris Cain             {
14681c83430SChris Cain                 log<level::ERR>(
14748002498SPatrick Williams                     std::format(
14881c83430SChris Cain                         "updatePcapBounds: Failed to update user powercap due to ",
14981c83430SChris Cain                         e.what())
15081c83430SChris Cain                         .c_str());
15181c83430SChris Cain             }
15281c83430SChris Cain         }
15340501a23SChris Cain     }
1545d66a0aaSChris Cain }
1555d66a0aaSChris Cain 
15681c83430SChris Cain // Get value of power cap to send to the OCC (output/DC power)
getOccInput(uint32_t pcap,bool pcapEnabled)1574cea4d2bSAndrew Geissler uint32_t PowerCap::getOccInput(uint32_t pcap, bool pcapEnabled)
1584cea4d2bSAndrew Geissler {
1594cea4d2bSAndrew Geissler     if (!pcapEnabled)
1604cea4d2bSAndrew Geissler     {
1614cea4d2bSAndrew Geissler         // Pcap disabled, return 0 to indicate disabled
1624cea4d2bSAndrew Geissler         return 0;
1634cea4d2bSAndrew Geissler     }
1644cea4d2bSAndrew Geissler 
1654cea4d2bSAndrew Geissler     // If pcap is not disabled then just return the pcap with the derating
16681c83430SChris Cain     // factor applied (output/DC power).
1674cea4d2bSAndrew Geissler     return ((static_cast<uint64_t>(pcap) * PS_DERATING_FACTOR) / 100);
1684cea4d2bSAndrew Geissler }
1694cea4d2bSAndrew Geissler 
getPcap()17052cf26a8SAndrew Geissler uint32_t PowerCap::getPcap()
17152cf26a8SAndrew Geissler {
172f3b7514eSGeorge Liu     utils::PropertyValue pcap{};
173f3b7514eSGeorge Liu     try
17452cf26a8SAndrew Geissler     {
175f3b7514eSGeorge Liu         pcap = utils::getProperty(PCAP_PATH, PCAP_INTERFACE, POWER_CAP_PROP);
17652cf26a8SAndrew Geissler 
177305ff8b1SPatrick Williams         return std::get<uint32_t>(pcap);
17852cf26a8SAndrew Geissler     }
179af40808fSPatrick Williams     catch (const sdbusplus::exception_t& e)
180f3b7514eSGeorge Liu     {
181f3b7514eSGeorge Liu         log<level::ERR>("Failed to get PowerCap property",
182f3b7514eSGeorge Liu                         entry("ERROR=%s", e.what()),
183f3b7514eSGeorge Liu                         entry("PATH=%s", PCAP_PATH));
184f3b7514eSGeorge Liu 
185f3b7514eSGeorge Liu         return 0;
186f3b7514eSGeorge Liu     }
187f3b7514eSGeorge Liu }
18852cf26a8SAndrew Geissler 
getPcapEnabled()18952cf26a8SAndrew Geissler bool PowerCap::getPcapEnabled()
19052cf26a8SAndrew Geissler {
191f3b7514eSGeorge Liu     utils::PropertyValue pcapEnabled{};
192f3b7514eSGeorge Liu     try
19352cf26a8SAndrew Geissler     {
194f3b7514eSGeorge Liu         pcapEnabled = utils::getProperty(PCAP_PATH, PCAP_INTERFACE,
195f3b7514eSGeorge Liu                                          POWER_CAP_ENABLE_PROP);
19652cf26a8SAndrew Geissler 
197305ff8b1SPatrick Williams         return std::get<bool>(pcapEnabled);
19852cf26a8SAndrew Geissler     }
199af40808fSPatrick Williams     catch (const sdbusplus::exception_t& e)
200f3b7514eSGeorge Liu     {
201f3b7514eSGeorge Liu         log<level::ERR>("Failed to get PowerCapEnable property",
202f3b7514eSGeorge Liu                         entry("ERROR=%s", e.what()),
203f3b7514eSGeorge Liu                         entry("PATH=%s", PCAP_PATH));
204f3b7514eSGeorge Liu 
205f3b7514eSGeorge Liu         return false;
206f3b7514eSGeorge Liu     }
207f3b7514eSGeorge Liu }
20832016d18SAndrew Geissler 
getPcapFilename(const std::regex & expr)2095d66a0aaSChris Cain fs::path PowerCap::getPcapFilename(const std::regex& expr)
210eaaf3b28SMatt Spinler {
2115d66a0aaSChris Cain     if (pcapBasePathname.empty())
2125d66a0aaSChris Cain     {
2135d66a0aaSChris Cain         pcapBasePathname = occStatus.getHwmonPath();
214e2d0a43cSChris Cain     }
215e2d0a43cSChris Cain 
216e2d0a43cSChris Cain     if (fs::exists(pcapBasePathname))
2175d66a0aaSChris Cain     {
218e2d0a43cSChris Cain         // Search for pcap file based on the supplied expr
2195d66a0aaSChris Cain         for (auto& file : fs::directory_iterator(pcapBasePathname))
220eaaf3b28SMatt Spinler         {
221eaaf3b28SMatt Spinler             if (std::regex_search(file.path().string(), expr))
222eaaf3b28SMatt Spinler             {
223e2d0a43cSChris Cain                 // Found match
2245d66a0aaSChris Cain                 return file;
225eaaf3b28SMatt Spinler             }
226eaaf3b28SMatt Spinler         }
227e2d0a43cSChris Cain     }
228e2d0a43cSChris Cain     else
229e2d0a43cSChris Cain     {
23048002498SPatrick Williams         log<level::ERR>(std::format("Power Cap base filename not found: {}",
231e2d0a43cSChris Cain                                     pcapBasePathname.c_str())
232e2d0a43cSChris Cain                             .c_str());
233e2d0a43cSChris Cain     }
234e2d0a43cSChris Cain 
2355d66a0aaSChris Cain     // return empty path
2365d66a0aaSChris Cain     return fs::path{};
237eaaf3b28SMatt Spinler }
238eaaf3b28SMatt Spinler 
23981c83430SChris Cain // Write the user power cap to sysfs (output/DC power)
24040501a23SChris Cain // This will trigger the driver to send the cap to the OCC
writeOcc(uint32_t pcapValue)2416ac874e1SAndrew Geissler void PowerCap::writeOcc(uint32_t pcapValue)
2426ac874e1SAndrew Geissler {
243d4c19a07SChris Cain     if (!occStatus.occActive())
244d4c19a07SChris Cain     {
245d4c19a07SChris Cain         // OCC not running, skip update
246d4c19a07SChris Cain         return;
247d4c19a07SChris Cain     }
248d4c19a07SChris Cain 
2495d66a0aaSChris Cain     // Build the hwmon string to write the user power cap
2505d66a0aaSChris Cain     fs::path fileName = getPcapFilename(std::regex{"power\\d+_cap_user$"});
2515d66a0aaSChris Cain     if (fileName.empty())
252eaaf3b28SMatt Spinler     {
253b6535e89SChris Cain         log<level::ERR>(
25448002498SPatrick Williams             std::format("Could not find a power cap file to write to: {})",
2555d66a0aaSChris Cain                         pcapBasePathname.c_str())
256b6535e89SChris Cain                 .c_str());
257eaaf3b28SMatt Spinler         return;
258eaaf3b28SMatt Spinler     }
259eaaf3b28SMatt Spinler 
260eaaf3b28SMatt Spinler     uint64_t microWatts = pcapValue * 1000000ull;
261eaaf3b28SMatt Spinler 
262eaaf3b28SMatt Spinler     auto pcapString{std::to_string(microWatts)};
2636ac874e1SAndrew Geissler 
2646ac874e1SAndrew Geissler     // Open the hwmon file and write the power cap
2655d66a0aaSChris Cain     std::ofstream file(fileName, std::ios::out);
2665d66a0aaSChris Cain     if (file)
2675d66a0aaSChris Cain     {
26848002498SPatrick Williams         log<level::INFO>(std::format("Writing {}uW to {}", pcapString.c_str(),
2695d66a0aaSChris Cain                                      fileName.c_str())
2705d66a0aaSChris Cain                              .c_str());
2716ac874e1SAndrew Geissler         file << pcapString;
2726ac874e1SAndrew Geissler         file.close();
2735d66a0aaSChris Cain     }
2745d66a0aaSChris Cain     else
2755d66a0aaSChris Cain     {
27648002498SPatrick Williams         log<level::ERR>(std::format("Failed writing {}uW to {} (errno={})",
2775d66a0aaSChris Cain                                     microWatts, fileName.c_str(), errno)
2785d66a0aaSChris Cain                             .c_str());
2795d66a0aaSChris Cain     }
2805d66a0aaSChris Cain 
2816ac874e1SAndrew Geissler     return;
2826ac874e1SAndrew Geissler }
2836ac874e1SAndrew Geissler 
28481c83430SChris Cain // Read the current user power cap from sysfs as input/AC power
readUserCapHwmon()28540501a23SChris Cain uint32_t PowerCap::readUserCapHwmon()
28640501a23SChris Cain {
28740501a23SChris Cain     uint32_t userCap = 0;
28840501a23SChris Cain 
28940501a23SChris Cain     // Get the sysfs filename for the user power cap
29040501a23SChris Cain     fs::path userCapName = getPcapFilename(std::regex{"power\\d+_cap_user$"});
29140501a23SChris Cain     if (userCapName.empty())
29240501a23SChris Cain     {
29340501a23SChris Cain         log<level::ERR>(
29448002498SPatrick Williams             std::format(
29540501a23SChris Cain                 "readUserCapHwmon: Could not find a power cap file to read: {})",
29640501a23SChris Cain                 pcapBasePathname.c_str())
29740501a23SChris Cain                 .c_str());
29840501a23SChris Cain         return 0;
29940501a23SChris Cain     }
30040501a23SChris Cain 
30140501a23SChris Cain     // Open the sysfs file and read the power cap
30240501a23SChris Cain     std::ifstream file(userCapName, std::ios::in);
30340501a23SChris Cain     if (file)
30440501a23SChris Cain     {
305e2d0a43cSChris Cain         uint64_t cap;
30640501a23SChris Cain         file >> cap;
30740501a23SChris Cain         file.close();
30881c83430SChris Cain         // Convert to input/AC Power in Watts
30981c83430SChris Cain         userCap = (cap / (PS_DERATING_FACTOR / 100.0) / 1000000);
31040501a23SChris Cain     }
31140501a23SChris Cain     else
31240501a23SChris Cain     {
31340501a23SChris Cain         log<level::ERR>(
31448002498SPatrick Williams             std::format("readUserCapHwmon: Failed reading {} (errno={})",
31540501a23SChris Cain                         userCapName.c_str(), errno)
31640501a23SChris Cain                 .c_str());
31740501a23SChris Cain     }
31840501a23SChris Cain 
31940501a23SChris Cain     return userCap;
32040501a23SChris Cain }
32140501a23SChris Cain 
pcapChanged(sdbusplus::message_t & msg)322af40808fSPatrick Williams void PowerCap::pcapChanged(sdbusplus::message_t& msg)
32332016d18SAndrew Geissler {
32432016d18SAndrew Geissler     if (!occStatus.occActive())
32532016d18SAndrew Geissler     {
32632016d18SAndrew Geissler         // Nothing to do
32732016d18SAndrew Geissler         return;
32832016d18SAndrew Geissler     }
32952cf26a8SAndrew Geissler 
33052cf26a8SAndrew Geissler     uint32_t pcap = 0;
33152cf26a8SAndrew Geissler     bool pcapEnabled = false;
33252cf26a8SAndrew Geissler 
33352cf26a8SAndrew Geissler     std::string msgSensor;
334e0962703SPatrick Williams     std::map<std::string, std::variant<uint32_t, bool>> msgData;
33552cf26a8SAndrew Geissler     msg.read(msgSensor, msgData);
33652cf26a8SAndrew Geissler 
3375d66a0aaSChris Cain     bool changeFound = false;
3385d66a0aaSChris Cain     for (const auto& [prop, value] : msgData)
33952cf26a8SAndrew Geissler     {
3405d66a0aaSChris Cain         if (prop == POWER_CAP_PROP)
3415d66a0aaSChris Cain         {
3425d66a0aaSChris Cain             pcap = std::get<uint32_t>(value);
34352cf26a8SAndrew Geissler             pcapEnabled = getPcapEnabled();
3445d66a0aaSChris Cain             changeFound = true;
34552cf26a8SAndrew Geissler         }
3465d66a0aaSChris Cain         else if (prop == POWER_CAP_ENABLE_PROP)
34752cf26a8SAndrew Geissler         {
3485d66a0aaSChris Cain             pcapEnabled = std::get<bool>(value);
34952cf26a8SAndrew Geissler             pcap = getPcap();
3505d66a0aaSChris Cain             changeFound = true;
35152cf26a8SAndrew Geissler         }
35252cf26a8SAndrew Geissler         else
35352cf26a8SAndrew Geissler         {
3545d66a0aaSChris Cain             // Ignore other properties
3555d66a0aaSChris Cain             log<level::DEBUG>(
35648002498SPatrick Williams                 std::format(
3575d66a0aaSChris Cain                     "pcapChanged: Unknown power cap property changed {} to {}",
3585d66a0aaSChris Cain                     prop.c_str(), std::get<uint32_t>(value))
3595d66a0aaSChris Cain                     .c_str());
36052cf26a8SAndrew Geissler         }
36152cf26a8SAndrew Geissler     }
36252cf26a8SAndrew Geissler 
36381c83430SChris Cain     // Validate the cap is within supported range
36481c83430SChris Cain     uint32_t capSoftMin, capHardMin, capMax;
36581c83430SChris Cain     readDbusPcapLimits(capSoftMin, capHardMin, capMax);
36681c83430SChris Cain     if (((pcap > 0) && (pcap < capSoftMin)) || ((pcap == 0) && (pcapEnabled)))
36781c83430SChris Cain     {
36881c83430SChris Cain         log<level::ERR>(
36948002498SPatrick Williams             std::format(
37081c83430SChris Cain                 "pcapChanged: Power cap of {}W is lower than allowed (soft min:{}, min:{}) - using soft min",
37181c83430SChris Cain                 pcap, capSoftMin, capHardMin)
37281c83430SChris Cain                 .c_str());
37381c83430SChris Cain         pcap = capSoftMin;
37481c83430SChris Cain         utils::setProperty(PCAP_PATH, PCAP_INTERFACE, POWER_CAP_PROP, pcap);
37581c83430SChris Cain     }
37681c83430SChris Cain     else if (pcap > capMax)
37781c83430SChris Cain     {
37881c83430SChris Cain         log<level::ERR>(
37948002498SPatrick Williams             std::format(
38081c83430SChris Cain                 "pcapChanged: Power cap of {}W is higher than allowed (max:{}) - using max",
38181c83430SChris Cain                 pcap, capSoftMin, capHardMin)
38281c83430SChris Cain                 .c_str());
38381c83430SChris Cain         pcap = capMax;
38481c83430SChris Cain         utils::setProperty(PCAP_PATH, PCAP_INTERFACE, POWER_CAP_PROP, pcap);
38581c83430SChris Cain     }
38681c83430SChris Cain 
3875d66a0aaSChris Cain     if (changeFound)
3885d66a0aaSChris Cain     {
389b6535e89SChris Cain         log<level::INFO>(
39048002498SPatrick Williams             std::format(
3915d66a0aaSChris Cain                 "Power Cap Property Change (cap={}W (input), enabled={})", pcap,
3925d66a0aaSChris Cain                 pcapEnabled ? 'y' : 'n')
393b6535e89SChris Cain                 .c_str());
39452cf26a8SAndrew Geissler 
39552cf26a8SAndrew Geissler         // Determine desired action to write to occ
3964cea4d2bSAndrew Geissler         auto occInput = getOccInput(pcap, pcapEnabled);
39752cf26a8SAndrew Geissler         // Write action to occ
3986ac874e1SAndrew Geissler         writeOcc(occInput);
3995d66a0aaSChris Cain     }
40052cf26a8SAndrew Geissler 
40152cf26a8SAndrew Geissler     return;
40232016d18SAndrew Geissler }
40332016d18SAndrew Geissler 
4045d66a0aaSChris Cain // Update the Power Cap bounds on DBus
updateDbusPcapLimits(uint32_t softMin,uint32_t hardMin,uint32_t max)40581c83430SChris Cain bool PowerCap::updateDbusPcapLimits(uint32_t softMin, uint32_t hardMin,
40681c83430SChris Cain                                     uint32_t max)
4075d66a0aaSChris Cain {
4085d66a0aaSChris Cain     bool complete = true;
4095d66a0aaSChris Cain 
4105d66a0aaSChris Cain     try
4115d66a0aaSChris Cain     {
412613dc90dSChris Cain         utils::setProperty(PCAP_PATH, PCAP_INTERFACE, POWER_CAP_SOFT_MIN,
413613dc90dSChris Cain                            softMin);
414613dc90dSChris Cain     }
415af40808fSPatrick Williams     catch (const sdbusplus::exception_t& e)
416613dc90dSChris Cain     {
417613dc90dSChris Cain         log<level::ERR>(
41848002498SPatrick Williams             std::format(
41981c83430SChris Cain                 "updateDbusPcapLimits: Failed to set SOFT PCAP to {}W due to {}",
420613dc90dSChris Cain                 softMin, e.what())
421613dc90dSChris Cain                 .c_str());
422613dc90dSChris Cain         complete = false;
423613dc90dSChris Cain     }
424613dc90dSChris Cain 
425613dc90dSChris Cain     try
426613dc90dSChris Cain     {
4275d66a0aaSChris Cain         utils::setProperty(PCAP_PATH, PCAP_INTERFACE, POWER_CAP_HARD_MIN,
4285d66a0aaSChris Cain                            hardMin);
4295d66a0aaSChris Cain     }
430af40808fSPatrick Williams     catch (const sdbusplus::exception_t& e)
4315d66a0aaSChris Cain     {
4325d66a0aaSChris Cain         log<level::ERR>(
43348002498SPatrick Williams             std::format(
43481c83430SChris Cain                 "updateDbusPcapLimits: Failed to set HARD PCAP to {}W due to {}",
4355d66a0aaSChris Cain                 hardMin, e.what())
4365d66a0aaSChris Cain                 .c_str());
4375d66a0aaSChris Cain         complete = false;
4385d66a0aaSChris Cain     }
4395d66a0aaSChris Cain 
4405d66a0aaSChris Cain     try
4415d66a0aaSChris Cain     {
4425d66a0aaSChris Cain         utils::setProperty(PCAP_PATH, PCAP_INTERFACE, POWER_CAP_MAX, max);
4435d66a0aaSChris Cain     }
444af40808fSPatrick Williams     catch (const sdbusplus::exception_t& e)
4455d66a0aaSChris Cain     {
4465d66a0aaSChris Cain         log<level::ERR>(
44748002498SPatrick Williams             std::format(
44881c83430SChris Cain                 "updateDbusPcapLimits: Failed to set MAX PCAP to {}W due to {}",
44981c83430SChris Cain                 max, e.what())
4505d66a0aaSChris Cain                 .c_str());
4515d66a0aaSChris Cain         complete = false;
4525d66a0aaSChris Cain     }
4535d66a0aaSChris Cain 
4545d66a0aaSChris Cain     return complete;
4555d66a0aaSChris Cain }
45681c83430SChris Cain 
45781c83430SChris Cain // Read the Power Cap bounds from DBus
readDbusPcapLimits(uint32_t & softMin,uint32_t & hardMin,uint32_t & max)45881c83430SChris Cain bool PowerCap::readDbusPcapLimits(uint32_t& softMin, uint32_t& hardMin,
45981c83430SChris Cain                                   uint32_t& max)
46081c83430SChris Cain {
46181c83430SChris Cain     bool complete = true;
46281c83430SChris Cain     utils::PropertyValue prop{};
46381c83430SChris Cain 
46481c83430SChris Cain     try
46581c83430SChris Cain     {
466*d7542c83SPatrick Williams         prop =
467*d7542c83SPatrick Williams             utils::getProperty(PCAP_PATH, PCAP_INTERFACE, POWER_CAP_SOFT_MIN);
46881c83430SChris Cain         softMin = std::get<uint32_t>(prop);
46981c83430SChris Cain     }
470af40808fSPatrick Williams     catch (const sdbusplus::exception_t& e)
47181c83430SChris Cain     {
47281c83430SChris Cain         log<level::ERR>(
47348002498SPatrick Williams             std::format("readDbusPcapLimits: Failed to get SOFT PCAP due to {}",
47481c83430SChris Cain                         e.what())
47581c83430SChris Cain                 .c_str());
47681c83430SChris Cain         softMin = 0;
47781c83430SChris Cain         complete = false;
47881c83430SChris Cain     }
47981c83430SChris Cain 
48081c83430SChris Cain     try
48181c83430SChris Cain     {
482*d7542c83SPatrick Williams         prop =
483*d7542c83SPatrick Williams             utils::getProperty(PCAP_PATH, PCAP_INTERFACE, POWER_CAP_HARD_MIN);
48481c83430SChris Cain         hardMin = std::get<uint32_t>(prop);
48581c83430SChris Cain     }
486af40808fSPatrick Williams     catch (const sdbusplus::exception_t& e)
48781c83430SChris Cain     {
48881c83430SChris Cain         log<level::ERR>(
48948002498SPatrick Williams             std::format("readDbusPcapLimits: Failed to get HARD PCAP due to {}",
49081c83430SChris Cain                         e.what())
49181c83430SChris Cain                 .c_str());
49281c83430SChris Cain         hardMin = 0;
49381c83430SChris Cain         complete = false;
49481c83430SChris Cain     }
49581c83430SChris Cain 
49681c83430SChris Cain     try
49781c83430SChris Cain     {
49881c83430SChris Cain         prop = utils::getProperty(PCAP_PATH, PCAP_INTERFACE, POWER_CAP_MAX);
49981c83430SChris Cain         max = std::get<uint32_t>(prop);
50081c83430SChris Cain     }
501af40808fSPatrick Williams     catch (const sdbusplus::exception_t& e)
50281c83430SChris Cain     {
50381c83430SChris Cain         log<level::ERR>(
50448002498SPatrick Williams             std::format("readDbusPcapLimits: Failed to get MAX PCAP due to {}",
50581c83430SChris Cain                         e.what())
50681c83430SChris Cain                 .c_str());
50781c83430SChris Cain         max = INT_MAX;
50881c83430SChris Cain         complete = false;
50981c83430SChris Cain     }
51081c83430SChris Cain 
51181c83430SChris Cain     return complete;
51281c83430SChris Cain }
51381c83430SChris Cain 
51494df8c90SGunnar Mills } // namespace powercap
51532016d18SAndrew Geissler 
51632016d18SAndrew Geissler } // namespace occ
51732016d18SAndrew Geissler 
51894df8c90SGunnar Mills } // namespace open_power
519