blob: fab3918f6238f82152b16da8c218cdbae179372d [file] [log] [blame]
Andrew Geissler32016d12017-06-20 15:46:52 -05001#pragma once
2
Gunnar Mills94df8c92018-09-14 14:50:03 -05003#include "config.h"
4
George Liuf3b75142021-06-10 11:22:50 +08005#include "utils.hpp"
Gunnar Mills94df8c92018-09-14 14:50:03 -05006
Andrew Geissler32016d12017-06-20 15:46:52 -05007#include <sdbusplus/bus.hpp>
8#include <sdbusplus/bus/match.hpp>
Chris Caind6ced7c2022-10-17 17:11:07 -05009#include <xyz/openbmc_project/Control/Power/CapLimits/server.hpp>
Andrew Geissler32016d12017-06-20 15:46:52 -050010
George Liubcef3b42021-09-10 12:39:02 +080011#include <filesystem>
Chris Cain5d66a0a2022-02-09 08:52:10 -060012#include <regex>
George Liub5ca1012021-09-10 12:53:11 +080013
Andrew Geissler32016d12017-06-20 15:46:52 -050014namespace open_power
15{
16namespace occ
17{
Chris Cain5d66a0a2022-02-09 08:52:10 -060018class Status;
19
Andrew Geissler32016d12017-06-20 15:46:52 -050020namespace powercap
21{
22
23namespace sdbusRule = sdbusplus::bus::match::rules;
Chris Cain5d66a0a2022-02-09 08:52:10 -060024namespace fs = std::filesystem;
Andrew Geissler32016d12017-06-20 15:46:52 -050025
Chris Caind6ced7c2022-10-17 17:11:07 -050026constexpr auto PCAPLIMITS_PATH =
27 "/xyz/openbmc_project/control/host0/power_cap_limits";
28
29namespace Base = sdbusplus::xyz::openbmc_project::Control::Power::server;
30using CapLimitsInterface = sdbusplus::server::object_t<Base::CapLimits>;
31
32constexpr auto PCAPDATA_FILE_VERSION = 1;
33struct PowerCapData
34{
35 uint32_t version = PCAPDATA_FILE_VERSION;
36 bool initialized = false;
37 uint32_t softMin = 0x0000;
38 uint32_t hardMin = 0x0000;
39 uint32_t max = UINT_MAX;
40};
41
42/** @class OccPersistCapData
43 * @brief Provides persistent container to store data for OCC
44 *
45 * Data is stored in filesystem
46 */
47class OccPersistCapData
48{
49 public:
50 ~OccPersistCapData() = default;
51 OccPersistCapData(const OccPersistCapData&) = default;
52 OccPersistCapData& operator=(const OccPersistCapData&) = default;
53 OccPersistCapData(OccPersistCapData&&) = default;
54 OccPersistCapData& operator=(OccPersistCapData&&) = default;
55
56 /** @brief Loads any saved power cap data */
57 OccPersistCapData()
58 {
59 load();
60 }
61
62 /** @brief Save Power Mode data to persistent file
63 *
64 * @param[in] softMin - soft minimum power cap in Watts
65 * @param[in] hardMin - hard minimum power cap in Watts
66 * @param[in] max - maximum power cap in Watts
67 */
68 void updateCapLimits(const uint32_t softMin, const uint32_t hardMin,
69 const uint32_t max)
70 {
71 capData.softMin = softMin;
72 capData.hardMin = hardMin;
73 capData.max = max;
74 capData.initialized = true;
75 save();
76 }
77
78 /** @brief Return the power cap limits
79 *
80 * @param[out] softMin - soft minimum power cap in Watts
81 * @param[out] hardMin - hard minimum power cap in Watts
82 * @param[out] max - maximum power cap in Watts
83 */
84 void getCapLimits(uint32_t& softMin, uint32_t& hardMin, uint32_t& max) const
85 {
86 // If not initialized yet, still return PowerCapData defaults
87 softMin = capData.softMin;
88 hardMin = capData.hardMin;
89 max = capData.max;
90 }
91
92 /** @brief Return true if the power cap limits are available */
93 bool limitsAvailable()
94 {
95 return (capData.initialized);
96 }
97
98 /** @brief Saves the Power Mode data in the filesystem. */
99 void save();
100
101 /** @brief Trace the Power Mode and IPS parameters. */
102 void print();
103
104 private:
105 /** @brief Power Mode data filename to store persistent data */
Chris Cain03a8fe32024-12-10 14:46:20 -0600106 static constexpr auto powerCapFilename = "powerCapLimitData";
Chris Caind6ced7c2022-10-17 17:11:07 -0500107
108 /** @brief Power Mode data object to be persisted */
109 PowerCapData capData;
110
111 /** @brief Loads the persisted power cap data from the filesystem. */
112 void load();
113};
114
Andrew Geissler32016d12017-06-20 15:46:52 -0500115/** @class PowerCap
116 * @brief Monitors for changes to the power cap and notifies occ
117 *
118 * The customer power cap is provided to the OCC by host TMGT when the occ
119 * first goes active or is reset. This code is responsible for sending
120 * the power cap to the OCC if the cap is changed while the occ is active.
121 */
122
Chris Caind6ced7c2022-10-17 17:11:07 -0500123class PowerCap : public CapLimitsInterface
Andrew Geissler32016d12017-06-20 15:46:52 -0500124{
Gunnar Mills94df8c92018-09-14 14:50:03 -0500125 public:
Andrew Geissler32016d12017-06-20 15:46:52 -0500126 /** @brief PowerCap object to inform occ of changes to cap
127 *
128 * This object will monitor for changes to the power cap setting and
129 * power cap enable properties. If a change is detected, and the occ
130 * is active, then this object will notify the OCC of the change.
131 *
Andrew Geissler32016d12017-06-20 15:46:52 -0500132 * @param[in] occStatus - The occ status object
133 */
Chris Cain5d66a0a2022-02-09 08:52:10 -0600134 explicit PowerCap(Status& occStatus) :
Chris Caind6ced7c2022-10-17 17:11:07 -0500135 CapLimitsInterface(utils::getBus(), PCAPLIMITS_PATH,
136 CapLimitsInterface::action::defer_emit),
George Liuf3b75142021-06-10 11:22:50 +0800137 occStatus(occStatus),
Andrew Geissler32016d12017-06-20 15:46:52 -0500138 pcapMatch(
George Liuf3b75142021-06-10 11:22:50 +0800139 utils::getBus(),
Gunnar Mills94df8c92018-09-14 14:50:03 -0500140 sdbusRule::member("PropertiesChanged") +
Andrew Geissler32016d12017-06-20 15:46:52 -0500141 sdbusRule::path(
142 "/xyz/openbmc_project/control/host0/power_cap") +
143 sdbusRule::argN(0, "xyz.openbmc_project.Control.Power.Cap") +
144 sdbusRule::interface("org.freedesktop.DBus.Properties"),
Gunnar Mills94df8c92018-09-14 14:50:03 -0500145 std::bind(std::mem_fn(&PowerCap::pcapChanged), this,
Chris Caind6ced7c2022-10-17 17:11:07 -0500146 std::placeholders::_1))
147 {
148 // Read the current limits from persistent data
149 uint32_t capSoftMin, capHardMin, capMax;
150 persistedData.getCapLimits(capSoftMin, capHardMin, capMax);
151 // Update limits on dbus
152 updateDbusPcapLimits(capSoftMin, capHardMin, capMax);
153 // CapLimit interface is now ready
154 this->emit_object_added();
155 };
Andrew Geissler32016d12017-06-20 15:46:52 -0500156
Chris Cain81c83432022-06-27 08:21:52 -0500157 /** @brief Return the appropriate value to write to the OCC (output/DC
158 * power)
Andrew Geissler4cea4d22017-07-10 15:13:33 -0500159 *
Chris Cain81c83432022-06-27 08:21:52 -0500160 * @param[in] pcap - Current user power cap setting (input/AC power)
Andrew Geissler4cea4d22017-07-10 15:13:33 -0500161 * @param[in] pcapEnabled - Current power cap enable setting
162 *
163 * @return The value to write to the occ user pcap
164 */
165 uint32_t getOccInput(uint32_t pcap, bool pcapEnabled);
166
Chris Cain5d66a0a2022-02-09 08:52:10 -0600167 /** @brief Read the power cap bounds from sysfs and update DBus */
168 void updatePcapBounds();
169
Gunnar Mills94df8c92018-09-14 14:50:03 -0500170 private:
Chris Caind6ced7c2022-10-17 17:11:07 -0500171 /** @brief Persisted power cap limits */
172 OccPersistCapData persistedData;
173
Andrew Geissler32016d12017-06-20 15:46:52 -0500174 /** @brief Callback for pcap setting changes
175 *
176 * Process change and inform OCC
177 *
178 * @param[in] msg - Data associated with pcap change signal
179 *
180 */
Patrick Williamsaf408082022-07-22 19:26:54 -0500181 void pcapChanged(sdbusplus::message_t& msg);
Andrew Geissler32016d12017-06-20 15:46:52 -0500182
Andrew Geissler52cf26a2017-07-06 12:56:32 -0500183 /** @brief Get the power cap property
184 *
185 * @return Power cap, 0 on failure to indicate no pcap
186 */
187 uint32_t getPcap();
188
189 /** @brief Get the power cap enable property
190 *
191 * @return Whether power cap enabled, will return false on error
192 */
193 bool getPcapEnabled();
194
Chris Cain81c83432022-06-27 08:21:52 -0500195 /** @brief Write the output/DC power cap to the occ hwmon entry
Andrew Geissler6ac874e2017-07-10 15:54:58 -0500196 *
197 * @param[in] pcapValue - Power cap value to write to OCC
198 */
199 void writeOcc(uint32_t pcapValue);
200
Chris Cain40501a22022-03-14 17:33:27 -0500201 /** @brief Read the user power cap from sysfs
202 *
203 * @return User power cap value in Watts or 0 if disabled
204 */
205 uint32_t readUserCapHwmon();
206
Matt Spinlereaaf3b22019-07-16 10:29:27 -0500207 /**
208 * @brief Returns the filename to use for the user power cap
209 *
210 * The file is of the form "powerX_cap_user", where X is any
211 * number.
212 *
Chris Cain5d66a0a2022-02-09 08:52:10 -0600213 * @param[in] expr - Regular expression of file to find
Matt Spinlereaaf3b22019-07-16 10:29:27 -0500214 *
Chris Cain5d66a0a2022-02-09 08:52:10 -0600215 * @return full path/filename, or empty path if not found.
Matt Spinlereaaf3b22019-07-16 10:29:27 -0500216 */
Chris Cain5d66a0a2022-02-09 08:52:10 -0600217 fs::path getPcapFilename(const std::regex& expr);
Lei YU41470e52017-11-30 16:03:50 +0800218
Andrew Geissler32016d12017-06-20 15:46:52 -0500219 /* @brief OCC Status object */
Gunnar Mills94df8c92018-09-14 14:50:03 -0500220 Status& occStatus;
Andrew Geissler32016d12017-06-20 15:46:52 -0500221
Gunnar Mills85e65202018-04-08 15:01:54 -0500222 /** @brief Used to subscribe to dbus pcap property changes **/
Andrew Geissler32016d12017-06-20 15:46:52 -0500223 sdbusplus::bus::match_t pcapMatch;
Chris Cain5d66a0a2022-02-09 08:52:10 -0600224
225 /** @brief Path to the sysfs files holding the cap properties **/
226 fs::path pcapBasePathname;
227
228 /** @brief Update the power cap bounds on DBus
229 *
Chris Cain613dc902022-04-08 09:56:22 -0500230 * @param[in] softMin - soft minimum power cap in Watts
Chris Cain5d66a0a2022-02-09 08:52:10 -0600231 * @param[in] hardMin - hard minimum power cap in Watts
232 * @param[in] pcapMax - maximum power cap in Watts
Chris Cain5d66a0a2022-02-09 08:52:10 -0600233 */
Chris Caind6ced7c2022-10-17 17:11:07 -0500234 void updateDbusPcapLimits(uint32_t softMin, uint32_t hardMin,
Chris Cain81c83432022-06-27 08:21:52 -0500235 uint32_t pcapMax);
Gunnar Mills94df8c92018-09-14 14:50:03 -0500236};
Andrew Geissler32016d12017-06-20 15:46:52 -0500237
Gunnar Mills94df8c92018-09-14 14:50:03 -0500238} // namespace powercap
Andrew Geissler32016d12017-06-20 15:46:52 -0500239
240} // namespace occ
241
Gunnar Mills94df8c92018-09-14 14:50:03 -0500242} // namespace open_power