blob: b2121840887fc658a38347bca44338039ab6804c [file] [log] [blame]
Chris Cain78e86012021-03-04 16:15:31 -06001#pragma once
2
Chris Cain78e86012021-03-04 16:15:31 -06003#include "config.h"
4
George Liubddcf852021-09-08 08:46:22 +08005#ifdef POWER10
Chris Cain36f9cde2021-11-22 11:18:21 -06006#include "occ_command.hpp"
Chris Cain78e86012021-03-04 16:15:31 -06007
Chris Cain36f9cde2021-11-22 11:18:21 -06008#include <cereal/archives/json.hpp>
9//#include <cereal/archives/binary.hpp>
10#include <cereal/cereal.hpp>
11#include <cereal/types/string.hpp>
12#include <cereal/types/tuple.hpp>
13#include <cereal/types/vector.hpp>
Chris Cain78e86012021-03-04 16:15:31 -060014#include <sdbusplus/bus.hpp>
15#include <sdbusplus/bus/match.hpp>
Chris Cain1be43372021-12-09 19:29:37 -060016#include <xyz/openbmc_project/Control/Power/IdlePowerSaver/server.hpp>
17#include <xyz/openbmc_project/Control/Power/Mode/server.hpp>
Chris Cain78e86012021-03-04 16:15:31 -060018
George Liubcef3b42021-09-10 12:39:02 +080019#include <filesystem>
George Liub5ca1012021-09-10 12:53:11 +080020
Chris Cain78e86012021-03-04 16:15:31 -060021namespace open_power
22{
23namespace occ
24{
Chris Cain36f9cde2021-11-22 11:18:21 -060025
26class Manager;
27
Chris Cain78e86012021-03-04 16:15:31 -060028namespace powermode
29{
Chris Cain1be43372021-12-09 19:29:37 -060030namespace Base = sdbusplus::xyz::openbmc_project::Control::Power::server;
31using ModeInterface = sdbusplus::server::object::object<Base::Mode>;
32using IpsInterface = sdbusplus::server::object::object<Base::IdlePowerSaver>;
33using namespace std::literals::string_literals;
Chris Cain78e86012021-03-04 16:15:31 -060034
35constexpr auto PMODE_PATH = "/xyz/openbmc_project/control/host0/power_mode";
36constexpr auto PMODE_INTERFACE = "xyz.openbmc_project.Control.Power.Mode";
37constexpr auto POWER_MODE_PROP = "PowerMode";
38
Chris Cain1d51da22021-09-21 14:13:41 -050039constexpr auto PIPS_PATH = "/xyz/openbmc_project/control/host0/power_ips";
40constexpr auto PIPS_INTERFACE =
41 "xyz.openbmc_project.Control.Power.IdlePowerSaver";
42constexpr auto IPS_ENABLED_PROP = "Enabled";
43constexpr auto IPS_ENTER_UTIL = "EnterUtilizationPercent";
44constexpr auto IPS_ENTER_TIME = "EnterDwellTime";
45constexpr auto IPS_EXIT_UTIL = "ExitUtilizationPercent";
46constexpr auto IPS_EXIT_TIME = "ExitDwellTime";
47
Chris Cain1be43372021-12-09 19:29:37 -060048const auto PMODE_DEFAULT_INTERFACE =
49 "xyz.openbmc_project.Configuration.PowerModeProperties"s;
50
Chris Cain36f9cde2021-11-22 11:18:21 -060051/** @brief Query the current Hypervisor target
52 * @return true if the current Hypervisor target is PowerVM
53 */
54bool isPowerVM();
55
Chris Cain78e86012021-03-04 16:15:31 -060056/** @brief Convert power mode string to OCC SysPwrMode value
57 *
58 * @param[in] i_modeString - power mode string
59 *
60 * @return SysPwrMode or SysPwrMode::NO_CHANGE if not found
61 */
62SysPwrMode convertStringToMode(const std::string& i_modeString);
63
Chris Cain1be43372021-12-09 19:29:37 -060064struct PowerModeData
Chris Cain36f9cde2021-11-22 11:18:21 -060065{
Chris Cain1be43372021-12-09 19:29:37 -060066 bool modeInitialized = false;
67 SysPwrMode mode = SysPwrMode::NO_CHANGE;
68 uint16_t oemModeData = 0x0000;
69 bool ipsInitialized = false;
70 bool ipsEnabled = true;
71 uint8_t ipsEnterUtil = 0;
72 uint16_t ipsEnterTime = 0;
73 uint8_t ipsExitUtil = 0;
74 uint16_t ipsExitTime = 0;
Chris Cain36f9cde2021-11-22 11:18:21 -060075
76 /** @brief Function specifying data to archive for cereal.
77 */
78 template <class Archive>
79 void serialize(Archive& archive)
80 {
Chris Cain1be43372021-12-09 19:29:37 -060081 archive(modeInitialized, mode, oemModeData, ipsInitialized, ipsEnabled,
82 ipsEnterUtil, ipsEnterTime, ipsExitUtil, ipsExitTime);
Chris Cain36f9cde2021-11-22 11:18:21 -060083 }
84};
85
86/** @class OccPersistData
87 * @brief Provides persistent container to store data for OCC
88 *
89 * Data is stored via cereal
90 */
91class OccPersistData
92{
93 public:
94 ~OccPersistData() = default;
95 OccPersistData(const OccPersistData&) = default;
96 OccPersistData& operator=(const OccPersistData&) = default;
97 OccPersistData(OccPersistData&&) = default;
98 OccPersistData& operator=(OccPersistData&&) = default;
99
Chris Cain1be43372021-12-09 19:29:37 -0600100 /** @brief Loads any saved power mode data */
Chris Cain36f9cde2021-11-22 11:18:21 -0600101 OccPersistData()
102 {
103 load();
104 }
105
106 /** @brief Save Power Mode data to persistent file
107 *
Chris Cain1be43372021-12-09 19:29:37 -0600108 * @param[in] newMode - desired System Power Mode
109 * @param[in] oemModeData - data required by some OEM Power Modes
Chris Cain36f9cde2021-11-22 11:18:21 -0600110 */
Chris Cain1be43372021-12-09 19:29:37 -0600111 void updateMode(const SysPwrMode newMode, const uint16_t oemModeData)
Chris Cain36f9cde2021-11-22 11:18:21 -0600112 {
Chris Cain1be43372021-12-09 19:29:37 -0600113 modeData.mode = newMode;
114 modeData.oemModeData = oemModeData;
115 modeData.modeInitialized = true;
Chris Cain36f9cde2021-11-22 11:18:21 -0600116 save();
117 }
118
Chris Cain1be43372021-12-09 19:29:37 -0600119 /** @brief Write Idle Power Saver parameters to persistent file
Chris Cain36f9cde2021-11-22 11:18:21 -0600120 *
Chris Cain1be43372021-12-09 19:29:37 -0600121 * @param[in] enabled - Idle Power Save status (true = enabled)
122 * @param[in] enterUtil - IPS Enter Utilization (%)
123 * @param[in] enterTime - IPS Enter Time (seconds)
124 * @param[in] exitUtil - IPS Exit Utilization (%)
125 * @param[in] exitTime - IPS Exit Time (seconds)
Chris Cain36f9cde2021-11-22 11:18:21 -0600126 */
Chris Cain1be43372021-12-09 19:29:37 -0600127 void updateIPS(const bool enabled, const uint8_t enterUtil,
128 const uint16_t enterTime, const uint8_t exitUtil,
129 const uint16_t exitTime)
Chris Cain36f9cde2021-11-22 11:18:21 -0600130 {
Chris Cain1be43372021-12-09 19:29:37 -0600131 modeData.ipsEnabled = enabled;
132 modeData.ipsEnterUtil = enterUtil;
133 modeData.ipsEnterTime = enterTime;
134 modeData.ipsExitUtil = exitUtil;
135 modeData.ipsExitTime = exitTime;
136 modeData.ipsInitialized = true;
137 save();
138 }
139
140 /** @brief Return the Power Mode and mode data
141 *
142 * @param[out] mode - current system power mode
143 * @param[out] oemModeData - frequency data for some OEM mode
144 *
145 * @returns true if mode was available
146 */
147 bool getMode(SysPwrMode& mode, uint16_t& oemModeData) const
148 {
149 if (!modeData.modeInitialized)
Chris Cain36f9cde2021-11-22 11:18:21 -0600150 {
151 return false;
152 }
153
Chris Cain1be43372021-12-09 19:29:37 -0600154 mode = modeData.mode;
155 oemModeData = modeData.oemModeData;
Chris Cain36f9cde2021-11-22 11:18:21 -0600156 return true;
157 }
158
Chris Cain1be43372021-12-09 19:29:37 -0600159 /** @brief Get the Idle Power Saver properties from DBus
160 *
161 * @param[out] enabled - Idle Power Save status (true = enabled)
162 * @param[out] enterUtil - IPS Enter Utilization (%)
163 * @param[out] enterTime - IPS Enter Time (seconds)
164 * @param[out] exitUtil - IPS Exit Utilization (%)
165 * @param[out] exitTime - IPS Exit Time (seconds)
166 *
167 * @return true if parameters were read successfully
168 */
169 bool getIPS(bool& enabled, uint8_t& enterUtil, uint16_t& enterTime,
170 uint8_t& exitUtil, uint16_t& exitTime)
171 {
172 if (!modeData.ipsInitialized)
173 {
174 return false;
175 }
176
177 enabled = modeData.ipsEnabled;
178 enterUtil = modeData.ipsEnterUtil;
179 enterTime = modeData.ipsEnterTime;
180 exitUtil = modeData.ipsExitUtil;
181 exitTime = modeData.ipsExitTime;
182 return true;
183 }
184
185 /** @brief Return true if the power mode is available */
186 bool modeAvailable()
187 {
188 return (modeData.modeInitialized);
189 }
190
191 /** @brief Return true if the power mode is available */
192 bool ipsAvailable()
193 {
194 return (modeData.ipsInitialized);
195 }
196
Chris Cain36f9cde2021-11-22 11:18:21 -0600197 /** @brief Saves the Power Mode data in the filesystem using cereal. */
198 void save();
199
Chris Cain1be43372021-12-09 19:29:37 -0600200 /** @brief Trace the Power Mode and IPS parameters. */
201 void print();
Chris Cain36f9cde2021-11-22 11:18:21 -0600202
203 private:
Chris Cain1be43372021-12-09 19:29:37 -0600204 /** @brief Power Mode data filename to store persistent data */
205 static constexpr auto powerModeFilename = "powerModeData";
Chris Cain36f9cde2021-11-22 11:18:21 -0600206
Chris Cain1be43372021-12-09 19:29:37 -0600207 /** @brief Power Mode data object to be persisted */
208 PowerModeData modeData;
Chris Cain36f9cde2021-11-22 11:18:21 -0600209
210 /** @brief Loads the OEM mode data in the filesystem using cereal. */
211 void load();
212};
213
Chris Cain78e86012021-03-04 16:15:31 -0600214/** @class PowerMode
215 * @brief Monitors for changes to the power mode and notifies occ
216 *
217 * The customer power mode is provided to the OCC by host TMGT when the occ
218 * first goes active or is reset. This code is responsible for sending
219 * the power mode to the OCC if the mode is changed while the occ is active.
220 */
221
Chris Cain1be43372021-12-09 19:29:37 -0600222class PowerMode : public ModeInterface, public IpsInterface
Chris Cain78e86012021-03-04 16:15:31 -0600223{
224 public:
225 /** @brief PowerMode object to inform occ of changes to mode
226 *
227 * This object will monitor for changes to the power mode setting.
228 * If a change is detected, and the occ is active, then this object will
229 * notify the OCC of the change.
230 *
Chris Cain1be43372021-12-09 19:29:37 -0600231 * @param[in] managerRef - manager object reference
232 * @param[in] modePath - Power Mode dbus path
233 * @param[in] ipsPath - Idle Power Saver dbus path
Chris Cain78e86012021-03-04 16:15:31 -0600234 */
Chris Cain1be43372021-12-09 19:29:37 -0600235 explicit PowerMode(const Manager& managerRef, const char* modePath,
236 const char* ipsPath) :
237 ModeInterface(utils::getBus(), modePath, false),
238 IpsInterface(utils::getBus(), ipsPath, false), manager(managerRef),
Chris Cain78e86012021-03-04 16:15:31 -0600239 pmodeMatch(utils::getBus(),
240 sdbusplus::bus::match::rules::propertiesChanged(
241 PMODE_PATH, PMODE_INTERFACE),
Chris Cain36f9cde2021-11-22 11:18:21 -0600242 [this](auto& msg) { this->modeChanged(msg); }),
243 ipsMatch(utils::getBus(),
244 sdbusplus::bus::match::rules::propertiesChanged(
245 PIPS_PATH, PIPS_INTERFACE),
246 [this](auto& msg) { this->ipsChanged(msg); }),
Chris Cain1be43372021-12-09 19:29:37 -0600247 defaultsUpdateMatch(
248 utils::getBus(),
249 sdbusplus::bus::match::rules::propertiesChangedNamespace(
250 "/xyz/openbmc_project/inventory", PMODE_DEFAULT_INTERFACE),
251 [this](auto& msg) { this->defaultsReady(msg); }),
252 masterOccSet(false), masterActive(false)
253 {
254 // restore Power Mode to DBus
255 SysPwrMode currentMode;
256 uint16_t oemModeData = 0;
257 if (getMode(currentMode, oemModeData))
258 {
259 updateDbusMode(currentMode);
260 }
261 // restore Idle Power Saver parameters to DBus
262 uint8_t enterUtil, exitUtil;
263 uint16_t enterTime, exitTime;
264 bool ipsEnabled;
265 if (getIPSParms(ipsEnabled, enterUtil, enterTime, exitUtil, exitTime))
266 {
267 updateDbusIPS(ipsEnabled, enterUtil, enterTime, exitUtil, exitTime);
268 }
269 };
Chris Cain36f9cde2021-11-22 11:18:21 -0600270
Chris Cain1be43372021-12-09 19:29:37 -0600271 /** @brief Initialize the persistent data with default values
272 *
273 * @return true if initialization completed
274 */
275 bool initPersistentData();
276
277 /** @brief Set the current power mode property
278 *
279 * @param[in] newMode - desired system power mode
280 * @param[in] oemModeData - data required by some OEM Power Modes
281 *
282 * @return true if mode accepted
283 */
284 bool setMode(const SysPwrMode newMode, const uint16_t oemModeData);
Chris Cain36f9cde2021-11-22 11:18:21 -0600285
286 /** @brief Send mode change command to the master OCC
287 * @return SUCCESS on success
288 */
289 CmdStatus sendModeChange();
290
291 /** @brief Send Idle Power Saver config data to the master OCC
292 * @return SUCCESS on success
293 */
294 CmdStatus sendIpsData();
295
Chris Cain6fa848a2022-01-24 14:54:38 -0600296 /** @brief Set the master OCC path
297 *
298 * @param[in] occPath - hwmon path for master OCC
299 */
300 void setMasterOcc(const std::string& occPath);
301
Chris Cain36f9cde2021-11-22 11:18:21 -0600302 /** @brief Notify object of master OCC state. If not acitve, no
303 * commands will be sent to the master OCC
304 *
305 * @param[in] isActive - true when master OCC is active
306 */
307 void setMasterActive(const bool isActive = true)
308 {
309 masterActive = isActive;
310 };
Chris Cain78e86012021-03-04 16:15:31 -0600311
312 private:
Chris Cain36f9cde2021-11-22 11:18:21 -0600313 /** @brief OCC manager object */
314 const Manager& manager;
315
316 /** @brief Pass-through occ path on the bus */
317 std::string path;
318
319 /** @brief OCC instance number */
320 int occInstance;
321
322 /** @brief Object to send commands to the OCC */
Chris Cain6fa848a2022-01-24 14:54:38 -0600323 std::unique_ptr<open_power::occ::OccCommand> occCmd;
Chris Cain36f9cde2021-11-22 11:18:21 -0600324
325 /** @brief Used to subscribe to dbus pmode property changes **/
326 sdbusplus::bus::match_t pmodeMatch;
327
328 /** @brief Used to subscribe to dbus IPS property changes **/
329 sdbusplus::bus::match_t ipsMatch;
330
Chris Cain1be43372021-12-09 19:29:37 -0600331 /** @brief Used to subscribe to dbus defaults property changes **/
332 sdbusplus::bus::match_t defaultsUpdateMatch;
333
Chris Cain36f9cde2021-11-22 11:18:21 -0600334 OccPersistData persistedData;
335
Chris Cain6fa848a2022-01-24 14:54:38 -0600336 /** @brief True when the master OCC has been established */
337 bool masterOccSet;
338
339 /** @brief True when the master OCC is active */
Chris Cain36f9cde2021-11-22 11:18:21 -0600340 bool masterActive;
341
Chris Cain78e86012021-03-04 16:15:31 -0600342 /** @brief Callback for pmode setting changes
343 *
344 * Process change and inform OCC
345 *
346 * @param[in] msg - Data associated with pmode change signal
347 *
348 */
349 void modeChanged(sdbusplus::message::message& msg);
350
Chris Cain1be43372021-12-09 19:29:37 -0600351 /** @brief Get the current power mode property
352 *
353 * @param[out] currentMode - current system power mode
354 * @param[out] oemModeData - frequency data for some OEM mode
355 *
356 * @return true if data read successfully
Chris Cain1d51da22021-09-21 14:13:41 -0500357 */
Chris Cain1be43372021-12-09 19:29:37 -0600358 bool getMode(SysPwrMode& currentMode, uint16_t& oemModeData);
Chris Cain1d51da22021-09-21 14:13:41 -0500359
Chris Cain36f9cde2021-11-22 11:18:21 -0600360 /** @brief Update the power mode property on DBus
361 *
362 * @param[in] newMode - desired power mode
363 *
364 * @return true on success
365 */
366 bool updateDbusMode(const SysPwrMode newMode);
367
Chris Cain1d51da22021-09-21 14:13:41 -0500368 /** @brief Callback for IPS setting changes
369 *
370 * Process change and inform OCC
371 *
Chris Cain36f9cde2021-11-22 11:18:21 -0600372 * @param[in] msg - Data associated with IPS change signal
Chris Cain1d51da22021-09-21 14:13:41 -0500373 *
374 */
375 void ipsChanged(sdbusplus::message::message& msg);
376
Chris Cain1be43372021-12-09 19:29:37 -0600377 /** @brief Get the Idle Power Saver properties
378 *
379 * @param[out] enabled - Idle Power Save status (true = enabled)
380 * @param[out] enterUtil - IPS Enter Utilization (%)
381 * @param[out] enterTime - IPS Enter Time (seconds)
382 * @param[out] exitUtil - IPS Exit Utilization (%)
383 * @param[out] exitTime - IPS Exit Time (seconds)
384 *
385 * @return true if data read successfully
Chris Cain36f9cde2021-11-22 11:18:21 -0600386 */
Chris Cain1be43372021-12-09 19:29:37 -0600387 bool getIPSParms(bool& enabled, uint8_t& enterUtil, uint16_t& enterTime,
388 uint8_t& exitUtil, uint16_t& exitTime);
389
390 /** Update the Idle Power Saver data on DBus
391 *
392 * @param[in] enabled - Idle Power Save status (true = enabled)
393 * @param[in] enterUtil - IPS Enter Utilization (%)
394 * @param[in] enterTime - IPS Enter Time (seconds)
395 * @param[in] exitUtil - IPS Exit Utilization (%)
396 * @param[in] exitTime - IPS Exit Time (seconds)
397 *
398 * @return true if parameters were set successfully
399 */
400 bool updateDbusIPS(const bool enabled, const uint8_t enterUtil,
401 const uint16_t enterTime, const uint8_t exitUtil,
402 const uint16_t exitTime);
403
404 /** @brief Callback for entity manager default changes
405 *
406 * Called when PowerModeProperties defaults are available
407 */
408 void defaultsReady(sdbusplus::message::message& msg);
409
410 /** @brief Get the default power mode property for this system type
411 *
412 * @param[out] defaultMode - default system power mode
413 *
414 * @return true if data read successfully
415 */
416 bool getDefaultMode(SysPwrMode& defaultMode);
417
418 /** @brief Get the default Idle Power Saver properties for this system type
419 *
420 * @param[out] enabled - Idle Power Save status (true = enabled)
421 * @param[out] enterUtil - IPS Enter Utilization (%)
422 * @param[out] enterTime - IPS Enter Time (seconds)
423 * @param[out] exitUtil - IPS Exit Utilization (%)
424 * @param[out] exitTime - IPS Exit Time (seconds)
425 *
426 * @return true if parameters were read successfully
427 */
428 bool getDefaultIPSParms(bool& enabled, uint8_t& enterUtil,
429 uint16_t& enterTime, uint8_t& exitUtil,
430 uint16_t& exitTime);
Chris Cain1d51da22021-09-21 14:13:41 -0500431};
432
Chris Cain78e86012021-03-04 16:15:31 -0600433} // namespace powermode
434
435} // namespace occ
436
437} // namespace open_power
438#endif