blob: 04a97876d259071ef30a58bfea889cb2fe61956a [file] [log] [blame]
Chris Cain36f9cde2021-11-22 11:18:21 -06001#include "powermode.hpp"
2
Chris Cain78e86012021-03-04 16:15:31 -06003#include <fmt/core.h>
4
Chris Cain36f9cde2021-11-22 11:18:21 -06005#include <com/ibm/Host/Target/server.hpp>
Chris Cain78e86012021-03-04 16:15:31 -06006#include <phosphor-logging/log.hpp>
Chris Cain78e86012021-03-04 16:15:31 -06007#include <xyz/openbmc_project/Control/Power/Mode/server.hpp>
8
George Liub5ca1012021-09-10 12:53:11 +08009#include <cassert>
Chris Cain36f9cde2021-11-22 11:18:21 -060010#include <fstream>
George Liub5ca1012021-09-10 12:53:11 +080011#include <regex>
12
Chris Cain78e86012021-03-04 16:15:31 -060013namespace open_power
14{
15namespace occ
16{
17namespace powermode
18{
19
20using namespace phosphor::logging;
21using Mode = sdbusplus::xyz::openbmc_project::Control::Power::server::Mode;
22
Chris Cain36f9cde2021-11-22 11:18:21 -060023// Called when DBus power mode gets changed
Chris Cain78e86012021-03-04 16:15:31 -060024void PowerMode::modeChanged(sdbusplus::message::message& msg)
25{
Chris Cain36f9cde2021-11-22 11:18:21 -060026 SysPwrMode newMode = SysPwrMode::NO_CHANGE;
Chris Cain78e86012021-03-04 16:15:31 -060027
Chris Cain78e86012021-03-04 16:15:31 -060028 std::map<std::string, std::variant<std::string>> properties{};
29 std::string interface;
30 std::string propVal;
31 msg.read(interface, properties);
32 const auto modeEntry = properties.find(POWER_MODE_PROP);
33 if (modeEntry != properties.end())
34 {
35 auto modeEntryValue = modeEntry->second;
36 propVal = std::get<std::string>(modeEntryValue);
Chris Cain36f9cde2021-11-22 11:18:21 -060037 newMode = convertStringToMode(propVal);
38 if (newMode != SysPwrMode::NO_CHANGE)
Chris Cain78e86012021-03-04 16:15:31 -060039 {
Chris Cain36f9cde2021-11-22 11:18:21 -060040 // DBus mode changed, get rid of any OEM mode if set
41 persistedData.purge();
42
Chris Cain78e86012021-03-04 16:15:31 -060043 log<level::INFO>(
44 fmt::format("Power Mode Change Requested: {}", propVal)
45 .c_str());
46
Chris Cain36f9cde2021-11-22 11:18:21 -060047 // Send mode change to OCC
48 sendModeChange();
49 }
50 }
51}
52
53// Called from OCC PassThrough interface (via CE login / BMC command line)
54bool PowerMode::setMode(const SysPwrMode newMode, const uint16_t modeData)
55{
56 if (updateDbusMode(newMode) == false)
57 {
58 // Unsupported mode
59 return false;
60 }
61
62 // If new mode is valid customer mode, the DBus update will trigger the mode
63 // change request to OCC. For OEM modes, the request will be sent here.
64 if (VALID_OEM_POWER_MODE_SETTING(newMode))
65 {
66 // Save OEM mode
67 persistedData.writeModeFile(newMode, modeData);
68
69 // Send mode change to OCC
70 if (sendModeChange() != CmdStatus::SUCCESS)
71 {
72 // Mode change failed
73 return false;
Chris Cain78e86012021-03-04 16:15:31 -060074 }
75 }
76
Chris Cain36f9cde2021-11-22 11:18:21 -060077 return true;
Chris Cain78e86012021-03-04 16:15:31 -060078}
79
80// Convert PowerMode string to OCC SysPwrMode
Chris Cain36f9cde2021-11-22 11:18:21 -060081// Returns NO_CHANGE if OEM or unsupported mode
Chris Cain78e86012021-03-04 16:15:31 -060082SysPwrMode convertStringToMode(const std::string& i_modeString)
83{
84 SysPwrMode pmode = SysPwrMode::NO_CHANGE;
85
86 Mode::PowerMode mode = Mode::convertPowerModeFromString(i_modeString);
87 if (mode == Mode::PowerMode::MaximumPerformance)
88 {
89 pmode = SysPwrMode::MAX_PERF;
90 }
91 else if (mode == Mode::PowerMode::PowerSaving)
92 {
93 pmode = SysPwrMode::POWER_SAVING;
94 }
95 else if (mode == Mode::PowerMode::Static)
96 {
Chris Cain36f9cde2021-11-22 11:18:21 -060097 pmode = SysPwrMode::STATIC;
Chris Cain78e86012021-03-04 16:15:31 -060098 }
99 else
100 {
Chris Cain36f9cde2021-11-22 11:18:21 -0600101 if (mode != Mode::PowerMode::OEM)
102 {
103 log<level::ERR>(
104 fmt::format(
105 "convertStringToMode: Invalid Power Mode specified: {}",
106 i_modeString)
107 .c_str());
108 }
Chris Cain78e86012021-03-04 16:15:31 -0600109 }
110
111 return pmode;
112}
113
Chris Cain36f9cde2021-11-22 11:18:21 -0600114// Check if Hypervisor target is PowerVM
115bool isPowerVM()
Chris Cain1d51da22021-09-21 14:13:41 -0500116{
Chris Cain36f9cde2021-11-22 11:18:21 -0600117 using namespace open_power::occ::powermode;
118 namespace Hyper = sdbusplus::com::ibm::Host::server;
119 constexpr auto HYPE_PATH = "/com/ibm/host0/hypervisor";
120 constexpr auto HYPE_INTERFACE = "com.ibm.Host.Target";
121 constexpr auto HYPE_PROP = "Target";
122
123 bool powerVmTarget = false;
124
125 // This will throw exception on failure
126 auto& bus = utils::getBus();
127 auto service = utils::getService(HYPE_PATH, HYPE_INTERFACE);
128 auto method = bus.new_method_call(service.c_str(), HYPE_PATH,
129 "org.freedesktop.DBus.Properties", "Get");
130 method.append(HYPE_INTERFACE, HYPE_PROP);
131 auto reply = bus.call(method);
132
133 std::variant<std::string> hyperEntryValue;
134 reply.read(hyperEntryValue);
135 auto propVal = std::get<std::string>(hyperEntryValue);
136 if (Hyper::Target::convertHypervisorFromString(propVal) ==
137 Hyper::Target::Hypervisor::PowerVM)
138 {
139 powerVmTarget = true;
140 }
141
142 log<level::DEBUG>(
143 fmt::format("isPowerVM returning {}", powerVmTarget).c_str());
144
145 return powerVmTarget;
146}
147
148// Get the requested power mode from DBus
149SysPwrMode PowerMode::getDbusMode()
150{
151 using namespace open_power::occ::powermode;
152 SysPwrMode currentMode = SysPwrMode::NO_CHANGE;
153
154 // This will throw exception on failure
155 auto& bus = utils::getBus();
156 auto service = utils::getService(PMODE_PATH, PMODE_INTERFACE);
157 auto method = bus.new_method_call(service.c_str(), PMODE_PATH,
158 "org.freedesktop.DBus.Properties", "Get");
159 method.append(PMODE_INTERFACE, POWER_MODE_PROP);
160 auto reply = bus.call(method);
161
162 std::variant<std::string> stateEntryValue;
163 reply.read(stateEntryValue);
164 auto propVal = std::get<std::string>(stateEntryValue);
165
166 currentMode = powermode::convertStringToMode(propVal);
167 if (!VALID_POWER_MODE_SETTING(currentMode))
168 {
169 log<level::ERR>(
170 fmt::format(
171 "PowerMode::getDbusMode Invalid power mode found on DBus: {}",
172 currentMode)
173 .c_str());
174 currentMode = SysPwrMode::NO_CHANGE;
175 }
176
177 return currentMode;
178}
179
180// Set the power mode on DBus
181bool PowerMode::updateDbusMode(const SysPwrMode newMode)
182{
183 using namespace open_power::occ::powermode;
184 using namespace std::literals::string_literals;
185
186 if (!VALID_POWER_MODE_SETTING(newMode) &&
187 !VALID_OEM_POWER_MODE_SETTING(newMode))
188 {
189 log<level::ERR>(
190 fmt::format(
191 "PowerMode::updateDbusMode - Requested power mode not supported: {}",
192 newMode)
193 .c_str());
194 return false;
195 }
196
197 // Mode::PowerMode dBusMode;
198 std::string dBusMode;
199 switch (newMode)
200 {
201 case SysPwrMode::STATIC:
202 dBusMode = PMODE_INTERFACE + ".PowerMode.Static"s;
203 break;
204 case SysPwrMode::POWER_SAVING:
205 dBusMode = PMODE_INTERFACE + ".PowerMode.PowerSaving"s;
206 break;
207 case SysPwrMode::MAX_PERF:
208 dBusMode = PMODE_INTERFACE + ".PowerMode.MaximumPerformance"s;
209 break;
210 default:
211 dBusMode = PMODE_INTERFACE + ".PowerMode.OEM"s;
212 }
213
214 utils::setProperty(PMODE_PATH, PMODE_INTERFACE, POWER_MODE_PROP,
215 std::move(dBusMode));
216
217 return true;
218}
219
220// Send mode change request to the master OCC
221CmdStatus PowerMode::sendModeChange()
222{
223 CmdStatus status = CmdStatus::FAILURE;
224
225 if (!masterActive)
226 {
227 // Nothing to do
228 log<level::DEBUG>("PowerMode::sendModeChange: MODE CHANGE not enabled");
229 return CmdStatus::SUCCESS;
230 }
231
232 if (!isPowerVM())
233 {
234 // Mode change is only supported on PowerVM systems
235 log<level::DEBUG>(
236 "PowerMode::sendModeChange: MODE CHANGE does not get sent on non-PowerVM systems");
237 return CmdStatus::SUCCESS;
238 }
239
240 // Use OEM power mode if it was set
241 SysPwrMode newMode = SysPwrMode::NO_CHANGE;
242 uint16_t modeData = 0;
243 if (persistedData.getOemMode(newMode, modeData) == false)
244 {
245 // Read customer power mode from Dbus
246 newMode = getDbusMode();
247 }
248
249 if (VALID_POWER_MODE_SETTING(newMode) ||
250 VALID_OEM_POWER_MODE_SETTING(newMode))
251 {
252 std::vector<std::uint8_t> cmd, rsp;
253 cmd.reserve(9);
254 cmd.push_back(uint8_t(CmdType::SET_MODE_AND_STATE));
255 cmd.push_back(0x00); // Data Length (2 bytes)
256 cmd.push_back(0x06);
257 cmd.push_back(0x30); // Data (Version)
258 cmd.push_back(uint8_t(OccState::NO_CHANGE));
259 cmd.push_back(uint8_t(newMode));
260 cmd.push_back(modeData >> 8); // Mode Data (Freq Point)
261 cmd.push_back(modeData & 0xFF); //
262 cmd.push_back(0x00); // reserved
263 log<level::INFO>(
264 fmt::format(
265 "PowerMode::sendModeChange: SET_MODE({},{}) command to OCC{} ({} bytes)",
266 newMode, modeData, occInstance, cmd.size())
267 .c_str());
268 status = occCmd.send(cmd, rsp);
269 if (status == CmdStatus::SUCCESS)
270 {
271 if (rsp.size() == 5)
272 {
273 if (RspStatus::SUCCESS != RspStatus(rsp[2]))
274 {
275 log<level::ERR>(
276 fmt::format(
277 "PowerMode::sendModeChange: SET MODE failed with status 0x{:02X}",
278 rsp[2])
279 .c_str());
280 dump_hex(rsp);
281 status = CmdStatus::FAILURE;
282 }
283 }
284 else
285 {
286 log<level::ERR>(
287 "PowerMode::sendModeChange: INVALID SET MODE response");
288 dump_hex(rsp);
289 status = CmdStatus::FAILURE;
290 }
291 }
292 else
293 {
294 if (status == CmdStatus::OPEN_FAILURE)
295 {
296 // OCC not active yet
297 status = CmdStatus::SUCCESS;
298 }
299 else
300 {
301 log<level::ERR>("PowerMode::sendModeChange: SET_MODE FAILED!");
302 }
303 }
304 }
305 else
306 {
307 log<level::ERR>(
308 fmt::format(
309 "PowerMode::sendModeChange: Unable to set power mode to {}",
310 newMode)
311 .c_str());
312 status = CmdStatus::FAILURE;
313 }
314
315 return status;
316}
317
318void PowerMode::ipsChanged(sdbusplus::message::message& msg)
319{
320 if (!masterActive)
Chris Cain1d51da22021-09-21 14:13:41 -0500321 {
322 // Nothing to do
323 return;
324 }
325
326 bool parmsChanged = false;
327 std::string interface;
328 std::map<std::string, std::variant<bool, uint8_t, uint64_t>>
329 ipsProperties{};
330 msg.read(interface, ipsProperties);
331
332 auto ipsEntry = ipsProperties.find(IPS_ENABLED_PROP);
333 if (ipsEntry != ipsProperties.end())
334 {
335 const auto ipsEnabled = std::get<bool>(ipsEntry->second);
336 log<level::INFO>(
337 fmt::format("Idle Power Saver change: Enabled={}", ipsEnabled)
338 .c_str());
339 parmsChanged = true;
340 }
341 ipsEntry = ipsProperties.find(IPS_ENTER_UTIL);
342 if (ipsEntry != ipsProperties.end())
343 {
344 const auto enterUtil = std::get<uint8_t>(ipsEntry->second);
345 log<level::INFO>(
346 fmt::format("Idle Power Saver change: Enter Util={}%", enterUtil)
347 .c_str());
348 parmsChanged = true;
349 }
350 ipsEntry = ipsProperties.find(IPS_ENTER_TIME);
351 if (ipsEntry != ipsProperties.end())
352 {
353 std::chrono::milliseconds ms(std::get<uint64_t>(ipsEntry->second));
354 const auto enterTime =
355 std::chrono::duration_cast<std::chrono::seconds>(ms).count();
356 log<level::INFO>(
357 fmt::format("Idle Power Saver change: Enter Time={}sec", enterTime)
358 .c_str());
359 parmsChanged = true;
360 }
361 ipsEntry = ipsProperties.find(IPS_EXIT_UTIL);
362 if (ipsEntry != ipsProperties.end())
363 {
364 const auto exitUtil = std::get<uint8_t>(ipsEntry->second);
365 log<level::INFO>(
366 fmt::format("Idle Power Saver change: Exit Util={}%", exitUtil)
367 .c_str());
368 parmsChanged = true;
369 }
370 ipsEntry = ipsProperties.find(IPS_EXIT_TIME);
371 if (ipsEntry != ipsProperties.end())
372 {
373 std::chrono::milliseconds ms(std::get<uint64_t>(ipsEntry->second));
374 const auto exitTime =
375 std::chrono::duration_cast<std::chrono::seconds>(ms).count();
376 log<level::INFO>(
377 fmt::format("Idle Power Saver change: Exit Time={}sec", exitTime)
378 .c_str());
379 parmsChanged = true;
380 }
381
382 if (parmsChanged)
383 {
384 // Trigger mode change to OCC
Chris Cain36f9cde2021-11-22 11:18:21 -0600385 sendIpsData();
Chris Cain1d51da22021-09-21 14:13:41 -0500386 }
387
388 return;
389}
390
Chris Cain36f9cde2021-11-22 11:18:21 -0600391/** @brief Get the Idle Power Saver properties
392 * @return true if IPS is enabled
393 */
394bool PowerMode::getIPSParms(uint8_t& enterUtil, uint16_t& enterTime,
395 uint8_t& exitUtil, uint16_t& exitTime)
396{
397 using namespace open_power::occ::powermode;
398 // Defaults:
399 bool ipsEnabled = false; // Disabled
400 enterUtil = 8; // Enter Utilization (8%)
401 enterTime = 240; // Enter Delay Time (240s)
402 exitUtil = 12; // Exit Utilization (12%)
403 exitTime = 10; // Exit Delay Time (10s)
404
405 std::map<std::string, std::variant<bool, uint8_t, uint64_t>>
406 ipsProperties{};
407
408 // Get all IPS properties from DBus
409 try
410 {
411 auto& bus = utils::getBus();
412 auto service = utils::getService(PIPS_PATH, PIPS_INTERFACE);
413 auto method =
414 bus.new_method_call(service.c_str(), PIPS_PATH,
415 "org.freedesktop.DBus.Properties", "GetAll");
416 method.append(PIPS_INTERFACE);
417 auto reply = bus.call(method);
418 reply.read(ipsProperties);
419 }
420 catch (const sdbusplus::exception::exception& e)
421 {
422 log<level::ERR>(
423 fmt::format(
424 "Unable to read Idle Power Saver parameters so it will be disabled: {}",
425 e.what())
426 .c_str());
427 return ipsEnabled;
428 }
429
430 auto ipsEntry = ipsProperties.find(IPS_ENABLED_PROP);
431 if (ipsEntry != ipsProperties.end())
432 {
433 ipsEnabled = std::get<bool>(ipsEntry->second);
434 }
435 else
436 {
437 log<level::ERR>(
438 fmt::format("PowerMode::getIPSParms could not find property: {}",
439 IPS_ENABLED_PROP)
440 .c_str());
441 }
442
443 ipsEntry = ipsProperties.find(IPS_ENTER_UTIL);
444 if (ipsEntry != ipsProperties.end())
445 {
446 enterUtil = std::get<uint8_t>(ipsEntry->second);
447 }
448 else
449 {
450 log<level::ERR>(
451 fmt::format("PowerMode::getIPSParms could not find property: {}",
452 IPS_ENTER_UTIL)
453 .c_str());
454 }
455
456 ipsEntry = ipsProperties.find(IPS_ENTER_TIME);
457 if (ipsEntry != ipsProperties.end())
458 {
459 std::chrono::milliseconds ms(std::get<uint64_t>(ipsEntry->second));
460 enterTime =
461 std::chrono::duration_cast<std::chrono::seconds>(ms).count();
462 }
463 else
464 {
465 log<level::ERR>(
466 fmt::format("PowerMode::getIPSParms could not find property: {}",
467 IPS_ENTER_TIME)
468 .c_str());
469 }
470
471 ipsEntry = ipsProperties.find(IPS_EXIT_UTIL);
472 if (ipsEntry != ipsProperties.end())
473 {
474 exitUtil = std::get<uint8_t>(ipsEntry->second);
475 }
476 else
477 {
478 log<level::ERR>(
479 fmt::format("PowerMode::getIPSParms could not find property: {}",
480 IPS_EXIT_UTIL)
481 .c_str());
482 }
483
484 ipsEntry = ipsProperties.find(IPS_EXIT_TIME);
485 if (ipsEntry != ipsProperties.end())
486 {
487 std::chrono::milliseconds ms(std::get<uint64_t>(ipsEntry->second));
488 exitTime = std::chrono::duration_cast<std::chrono::seconds>(ms).count();
489 }
490 else
491 {
492 log<level::ERR>(
493 fmt::format("PowerMode::getIPSParms could not find property: {}",
494 IPS_EXIT_TIME)
495 .c_str());
496 }
497
498 if (enterUtil > exitUtil)
499 {
500 log<level::ERR>(
501 fmt::format(
502 "ERROR: Idle Power Saver Enter Utilization ({}%) is > Exit Utilization ({}%) - using Exit for both",
503 enterUtil, exitUtil)
504 .c_str());
505 enterUtil = exitUtil;
506 }
507
508 return ipsEnabled;
509}
510
511// Send Idle Power Saver config data to the master OCC
512CmdStatus PowerMode::sendIpsData()
513{
514 CmdStatus status = CmdStatus::FAILURE;
515
516 if (!masterActive)
517 {
518 // Nothing to do
519 return CmdStatus::SUCCESS;
520 }
521
522 if (!isPowerVM())
523 {
524 // Idle Power Saver data is only supported on PowerVM systems
525 log<level::DEBUG>(
526 "PowerMode::sendIpsData: SET_CFG_DATA[IPS] does not get sent on non-PowerVM systems");
527 return CmdStatus::SUCCESS;
528 }
529
530 uint8_t enterUtil, exitUtil;
531 uint16_t enterTime, exitTime;
532 const bool ipsEnabled =
533 getIPSParms(enterUtil, enterTime, exitUtil, exitTime);
534
535 log<level::INFO>(
536 fmt::format(
537 "Idle Power Saver Parameters: enabled:{}, enter:{}%/{}s, exit:{}%/{}s",
538 ipsEnabled, enterUtil, enterTime, exitUtil, exitTime)
539 .c_str());
540
541 std::vector<std::uint8_t> cmd, rsp;
542 cmd.reserve(12);
543 cmd.push_back(uint8_t(CmdType::SET_CONFIG_DATA));
544 cmd.push_back(0x00); // Data Length (2 bytes)
545 cmd.push_back(0x09); //
546 cmd.push_back(0x11); // Config Format: IPS Settings
547 cmd.push_back(0x00); // Version
548 cmd.push_back(ipsEnabled ? 1 : 0); // IPS Enable
549 cmd.push_back(enterTime >> 8); // Enter Delay Time
550 cmd.push_back(enterTime & 0xFF); //
551 cmd.push_back(enterUtil); // Enter Utilization
552 cmd.push_back(exitTime >> 8); // Exit Delay Time
553 cmd.push_back(exitTime & 0xFF); //
554 cmd.push_back(exitUtil); // Exit Utilization
555 log<level::INFO>(fmt::format("PowerMode::sendIpsData: SET_CFG_DATA[IPS] "
556 "command to OCC{} ({} bytes)",
557 occInstance, cmd.size())
558 .c_str());
559 status = occCmd.send(cmd, rsp);
560 if (status == CmdStatus::SUCCESS)
561 {
562 if (rsp.size() == 5)
563 {
564 if (RspStatus::SUCCESS != RspStatus(rsp[2]))
565 {
566 log<level::ERR>(
567 fmt::format(
568 "PowerMode::sendIpsData: SET_CFG_DATA[IPS] failed with status 0x{:02X}",
569 rsp[2])
570 .c_str());
571 dump_hex(rsp);
572 status = CmdStatus::FAILURE;
573 }
574 }
575 else
576 {
577 log<level::ERR>(
578 "PowerMode::sendIpsData: INVALID SET_CFG_DATA[IPS] response");
579 dump_hex(rsp);
580 status = CmdStatus::FAILURE;
581 }
582 }
583 else
584 {
585 if (status == CmdStatus::OPEN_FAILURE)
586 {
587 // OCC not active yet
588 status = CmdStatus::SUCCESS;
589 }
590 else
591 {
592 log<level::ERR>(
593 "PowerMode::sendIpsData: SET_CFG_DATA[IPS] FAILED!");
594 }
595 }
596
597 return status;
598}
599
600inline void OccPersistData::print()
601{
602 log<level::DEBUG>(
603 fmt::format(
604 "OccPersistData: OEM Mode: 0x{:02X}, OEM Mode Freq: {} (0x{:04X})",
605 oemData.oemMode, oemData.oemModeFreq, oemData.oemModeFreq)
606 .c_str());
607}
608
609// Saves the OEM mode data in the filesystem using cereal.
610void OccPersistData::save()
611{
612 std::filesystem::path opath =
613 std::filesystem::path{OCC_CONTROL_PERSIST_PATH} / oemModeFilename;
614
615 if (!std::filesystem::exists(opath.parent_path()))
616 {
617 std::filesystem::create_directory(opath.parent_path());
618 }
619
620 log<level::DEBUG>(
621 fmt::format("OccPersistData::save: Writing OEM persisted data to {}",
622 opath.c_str())
623 .c_str());
624 print();
625
626 std::ofstream stream{opath.c_str()};
627 cereal::JSONOutputArchive oarchive{stream};
628
629 oarchive(oemData);
630}
631
632// Loads the OEM mode data in the filesystem using cereal.
633void OccPersistData::load()
634{
635
636 std::filesystem::path ipath =
637 std::filesystem::path{OCC_CONTROL_PERSIST_PATH} / oemModeFilename;
638
639 if (!std::filesystem::exists(ipath))
640 {
641 return;
642 }
643
644 log<level::DEBUG>(
645 fmt::format("OccPersistData::load: Reading OEM persisted data from {}",
646 ipath.c_str())
647 .c_str());
648 try
649 {
650 std::ifstream stream{ipath.c_str()};
651 cereal::JSONInputArchive iarchive(stream);
652 iarchive(oemData);
653
654 oemSet = true;
655 }
656 catch (const std::exception& e)
657 {
658 auto error = errno;
659 log<level::ERR>(
660 fmt::format("OccPersistData::load: failed to read {}, errno={}",
661 ipath.c_str(), error)
662 .c_str());
663 }
664
665 print();
666}
667
668void OccPersistData::purge()
669{
670 std::filesystem::path opath =
671 std::filesystem::path{OCC_CONTROL_PERSIST_PATH} / oemModeFilename;
672
673 if (!std::filesystem::exists(opath))
674 {
675 return;
676 }
677
678 print();
679 log<level::DEBUG>("OccPersistData::purge() Removing OEM data");
680
681 oemSet = false;
682 oemData.oemMode = SysPwrMode::NO_CHANGE;
683 oemData.oemModeFreq = 0x0000;
684 remove(opath.c_str());
685}
686
Chris Cain78e86012021-03-04 16:15:31 -0600687} // namespace powermode
688
689} // namespace occ
690
691} // namespace open_power