blob: eede8d10f7e06b9e60d0113531de34e7e29ae10d [file] [log] [blame]
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +05301#include "config.h"
2
Gunnar Mills94df8c92018-09-14 14:50:03 -05003#include "occ_manager.hpp"
4
5#include "i2c_occ.hpp"
Chicago Duanbb895cb2021-06-18 19:37:16 +08006#include "occ_dbus.hpp"
Chris Cain4b82f3e2024-04-22 14:44:29 -05007#include "occ_errors.hpp"
Gunnar Mills94df8c92018-09-14 14:50:03 -05008#include "utils.hpp"
9
George Liub5ca1012021-09-10 12:53:11 +080010#include <phosphor-logging/elog-errors.hpp>
11#include <phosphor-logging/log.hpp>
12#include <xyz/openbmc_project/Common/error.hpp>
13
Matt Spinlerd267cec2021-09-01 14:49:19 -050014#include <chrono>
Chicago Duanbb895cb2021-06-18 19:37:16 +080015#include <cmath>
George Liubcef3b42021-09-10 12:39:02 +080016#include <filesystem>
Chris Cain36f9cde2021-11-22 11:18:21 -060017#include <fstream>
Chicago Duanbb895cb2021-06-18 19:37:16 +080018#include <regex>
Gunnar Mills94df8c92018-09-14 14:50:03 -050019
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +053020namespace open_power
21{
22namespace occ
23{
24
Matt Spinler8b8abee2021-08-25 15:18:21 -050025constexpr uint32_t fruTypeNotAvailable = 0xFF;
Matt Spinlera26f1522021-08-25 15:50:20 -050026constexpr auto fruTypeSuffix = "fru_type";
27constexpr auto faultSuffix = "fault";
28constexpr auto inputSuffix = "input";
Matt Spinlerace67d82021-10-18 13:41:57 -050029constexpr auto maxSuffix = "max";
Matt Spinler8b8abee2021-08-25 15:18:21 -050030
Chris Cain1718fd82022-02-16 16:39:50 -060031const auto HOST_ON_FILE = "/run/openbmc/host@0-on";
32
Chris Caina8857c52021-01-27 11:53:05 -060033using namespace phosphor::logging;
Chris Caina7b74dc2021-11-10 17:03:43 -060034using namespace std::literals::chrono_literals;
Chris Caina8857c52021-01-27 11:53:05 -060035
Matt Spinlera26f1522021-08-25 15:50:20 -050036template <typename T>
37T readFile(const std::string& path)
38{
39 std::ifstream ifs;
40 ifs.exceptions(std::ifstream::failbit | std::ifstream::badbit |
41 std::ifstream::eofbit);
42 T data;
43
44 try
45 {
46 ifs.open(path);
47 ifs >> data;
48 ifs.close();
49 }
50 catch (const std::exception& e)
51 {
52 auto err = errno;
53 throw std::system_error(err, std::generic_category());
54 }
55
56 return data;
57}
58
Chris Cainc33171b2024-05-24 16:14:50 -050059// findAndCreateObjects():
60// Takes care of getting the required objects created and
61// finds the available devices/processors.
62// (function is called everytime the discoverTimer expires)
63// - create the PowerMode object to control OCC modes
64// - create statusObjects for each OCC device found
65// - waits for OCC Active sensors PDRs to become available
66// - restart discoverTimer if all data is not available yet
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +053067void Manager::findAndCreateObjects()
68{
Matt Spinlerd267cec2021-09-01 14:49:19 -050069#ifndef POWER10
Deepak Kodihalli370f06b2017-10-25 04:26:07 -050070 for (auto id = 0; id < MAX_CPUS; ++id)
71 {
Deepak Kodihalli30417a12017-12-04 00:54:01 -060072 // Create one occ per cpu
73 auto occ = std::string(OCC_NAME) + std::to_string(id);
74 createObjects(occ);
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +053075 }
Matt Spinlerd267cec2021-09-01 14:49:19 -050076#else
Chris Cain613dc902022-04-08 09:56:22 -050077 if (!pmode)
78 {
79 // Create the power mode object
80 pmode = std::make_unique<powermode::PowerMode>(
81 *this, powermode::PMODE_PATH, powermode::PIPS_PATH, event);
82 }
83
Chris Cain1718fd82022-02-16 16:39:50 -060084 if (!fs::exists(HOST_ON_FILE))
Matt Spinlerd267cec2021-09-01 14:49:19 -050085 {
Chris Cainbae4d072022-02-28 09:46:50 -060086 static bool statusObjCreated = false;
87 if (!statusObjCreated)
Chris Cain1718fd82022-02-16 16:39:50 -060088 {
Chris Cainbae4d072022-02-28 09:46:50 -060089 // Create the OCCs based on on the /dev/occX devices
90 auto occs = findOCCsInDev();
Chris Cain1718fd82022-02-16 16:39:50 -060091
Chris Cainbae4d072022-02-28 09:46:50 -060092 if (occs.empty() || (prevOCCSearch.size() != occs.size()))
Chris Cain1718fd82022-02-16 16:39:50 -060093 {
Chris Cainbae4d072022-02-28 09:46:50 -060094 // Something changed or no OCCs yet, try again in 10s.
95 // Note on the first pass prevOCCSearch will be empty,
96 // so there will be at least one delay to give things
97 // a chance to settle.
98 prevOCCSearch = occs;
99
100 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600101 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -0600102 "Manager::findAndCreateObjects(): Waiting for OCCs (currently {})",
103 occs.size())
104 .c_str());
105
106 discoverTimer->restartOnce(10s);
107 }
108 else
109 {
110 // All OCCs appear to be available, create status objects
111
112 // createObjects requires OCC0 first.
113 std::sort(occs.begin(), occs.end());
114
115 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600116 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -0600117 "Manager::findAndCreateObjects(): Creating {} OCC Status Objects",
118 occs.size())
119 .c_str());
120 for (auto id : occs)
121 {
122 createObjects(std::string(OCC_NAME) + std::to_string(id));
123 }
124 statusObjCreated = true;
Chris Cain6d8f37a2022-04-29 13:46:01 -0500125 waitingForAllOccActiveSensors = true;
Chris Cainc86d80f2023-05-04 15:49:18 -0500126
127 // Find/update the processor path associated with each OCC
128 for (auto& obj : statusObjects)
129 {
130 obj->updateProcAssociation();
131 }
Chris Cainbae4d072022-02-28 09:46:50 -0600132 }
133 }
134
Chris Cain6d8f37a2022-04-29 13:46:01 -0500135 if (statusObjCreated && waitingForAllOccActiveSensors)
Chris Cainbae4d072022-02-28 09:46:50 -0600136 {
137 static bool tracedHostWait = false;
138 if (utils::isHostRunning())
139 {
140 if (tracedHostWait)
141 {
142 log<level::INFO>(
143 "Manager::findAndCreateObjects(): Host is running");
144 tracedHostWait = false;
145 }
Chris Cainbae4d072022-02-28 09:46:50 -0600146 checkAllActiveSensors();
147 }
148 else
149 {
150 if (!tracedHostWait)
151 {
152 log<level::INFO>(
153 "Manager::findAndCreateObjects(): Waiting for host to start");
154 tracedHostWait = true;
155 }
156 discoverTimer->restartOnce(30s);
Chris Cain7651c062024-05-02 14:14:06 -0500157#ifdef PLDM
Chris Cainc33171b2024-05-24 16:14:50 -0500158 if (throttlePldmTraceTimer->isEnabled())
Chris Cain7651c062024-05-02 14:14:06 -0500159 {
160 // Host is no longer running, disable throttle timer and
161 // make sure traces are not throttled
162 log<level::INFO>(
163 "findAndCreateObjects(): disabling sensor timer");
Chris Cainc33171b2024-05-24 16:14:50 -0500164 throttlePldmTraceTimer->setEnabled(false);
Chris Cain7651c062024-05-02 14:14:06 -0500165 pldmHandle->setTraceThrottle(false);
166 }
167#endif
Chris Cain1718fd82022-02-16 16:39:50 -0600168 }
169 }
Matt Spinlerd267cec2021-09-01 14:49:19 -0500170 }
171 else
172 {
Chris Cain1718fd82022-02-16 16:39:50 -0600173 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600174 std::format(
Chris Cain1718fd82022-02-16 16:39:50 -0600175 "Manager::findAndCreateObjects(): Waiting for {} to complete...",
176 HOST_ON_FILE)
177 .c_str());
178 discoverTimer->restartOnce(10s);
Matt Spinlerd267cec2021-09-01 14:49:19 -0500179 }
180#endif
181}
182
Chris Cainbae4d072022-02-28 09:46:50 -0600183#ifdef POWER10
184// Check if all occActive sensors are available
185void Manager::checkAllActiveSensors()
186{
187 static bool allActiveSensorAvailable = false;
188 static bool tracedSensorWait = false;
Chris Cain082a6ca2023-03-21 10:27:26 -0500189 static bool waitingForHost = false;
Chris Cainbae4d072022-02-28 09:46:50 -0600190
Chris Cain082a6ca2023-03-21 10:27:26 -0500191 if (open_power::occ::utils::isHostRunning())
Chris Cainbae4d072022-02-28 09:46:50 -0600192 {
Chris Cain082a6ca2023-03-21 10:27:26 -0500193 if (waitingForHost)
Chris Cainbae4d072022-02-28 09:46:50 -0600194 {
Chris Cain082a6ca2023-03-21 10:27:26 -0500195 waitingForHost = false;
196 log<level::INFO>("checkAllActiveSensors(): Host is now running");
197 }
198
199 // Start with the assumption that all are available
200 allActiveSensorAvailable = true;
201 for (auto& obj : statusObjects)
202 {
203 if ((!obj->occActive()) && (!obj->getPldmSensorReceived()))
Chris Cainbae4d072022-02-28 09:46:50 -0600204 {
Chris Cain7f89e4d2022-05-09 13:27:45 -0500205 auto instance = obj->getOccInstanceID();
206 // Check if sensor was queued while waiting for discovery
207 auto match = queuedActiveState.find(instance);
208 if (match != queuedActiveState.end())
Chris Cainbd551de2022-04-26 13:41:16 -0500209 {
Chris Cain7f89e4d2022-05-09 13:27:45 -0500210 queuedActiveState.erase(match);
Chris Cainbd551de2022-04-26 13:41:16 -0500211 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600212 std::format(
Chris Cain7f89e4d2022-05-09 13:27:45 -0500213 "checkAllActiveSensors(): OCC{} is ACTIVE (queued)",
Chris Cainbd551de2022-04-26 13:41:16 -0500214 instance)
215 .c_str());
Chris Cain7f89e4d2022-05-09 13:27:45 -0500216 obj->occActive(true);
Chris Cainbd551de2022-04-26 13:41:16 -0500217 }
Chris Cain7f89e4d2022-05-09 13:27:45 -0500218 else
219 {
220 allActiveSensorAvailable = false;
221 if (!tracedSensorWait)
222 {
223 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600224 std::format(
Chris Cain7f89e4d2022-05-09 13:27:45 -0500225 "checkAllActiveSensors(): Waiting on OCC{} Active sensor",
226 instance)
227 .c_str());
228 tracedSensorWait = true;
Chris Cain755af102024-02-27 16:09:51 -0600229#ifdef PLDM
Chris Cainc33171b2024-05-24 16:14:50 -0500230 // Make sure PLDM traces are not throttled
Chris Cain755af102024-02-27 16:09:51 -0600231 pldmHandle->setTraceThrottle(false);
Chris Cainc33171b2024-05-24 16:14:50 -0500232 // Start timer to throttle PLDM traces when timer
Chris Cain755af102024-02-27 16:09:51 -0600233 // expires
Chris Cainc33171b2024-05-24 16:14:50 -0500234 onPldmTimeoutCreatePel = false;
235 throttlePldmTraceTimer->restartOnce(5min);
Chris Cain755af102024-02-27 16:09:51 -0600236#endif
Chris Cain7f89e4d2022-05-09 13:27:45 -0500237 }
Patrick Williamsfb0a5c32024-02-28 11:27:00 -0600238#ifdef PLDM
Chris Cain7f89e4d2022-05-09 13:27:45 -0500239 pldmHandle->checkActiveSensor(obj->getOccInstanceID());
Patrick Williamsfb0a5c32024-02-28 11:27:00 -0600240#endif
Chris Cain7f89e4d2022-05-09 13:27:45 -0500241 break;
242 }
Chris Cainbd551de2022-04-26 13:41:16 -0500243 }
Chris Cainbae4d072022-02-28 09:46:50 -0600244 }
245 }
Chris Cain082a6ca2023-03-21 10:27:26 -0500246 else
247 {
248 if (!waitingForHost)
249 {
250 waitingForHost = true;
251 log<level::INFO>(
252 "checkAllActiveSensors(): Waiting for host to start");
Chris Cain7651c062024-05-02 14:14:06 -0500253#ifdef PLDM
Chris Cainc33171b2024-05-24 16:14:50 -0500254 if (throttlePldmTraceTimer->isEnabled())
Chris Cain7651c062024-05-02 14:14:06 -0500255 {
256 // Host is no longer running, disable throttle timer and
257 // make sure traces are not throttled
258 log<level::INFO>(
259 "checkAllActiveSensors(): disabling sensor timer");
Chris Cainc33171b2024-05-24 16:14:50 -0500260 throttlePldmTraceTimer->setEnabled(false);
Chris Cain7651c062024-05-02 14:14:06 -0500261 pldmHandle->setTraceThrottle(false);
262 }
263#endif
Chris Cain082a6ca2023-03-21 10:27:26 -0500264 }
265 }
Chris Cainbae4d072022-02-28 09:46:50 -0600266
267 if (allActiveSensorAvailable)
268 {
269 // All sensors were found, disable the discovery timer
Chris Cain7f89e4d2022-05-09 13:27:45 -0500270 if (discoverTimer->isEnabled())
271 {
Chris Cainf55f91a2022-05-27 13:40:15 -0500272 discoverTimer->setEnabled(false);
Chris Cain7f89e4d2022-05-09 13:27:45 -0500273 }
Chris Cain755af102024-02-27 16:09:51 -0600274#ifdef PLDM
Chris Cainc33171b2024-05-24 16:14:50 -0500275 if (throttlePldmTraceTimer->isEnabled())
Chris Cain755af102024-02-27 16:09:51 -0600276 {
277 // Disable throttle timer and make sure traces are not throttled
Chris Cainc33171b2024-05-24 16:14:50 -0500278 throttlePldmTraceTimer->setEnabled(false);
Chris Cain755af102024-02-27 16:09:51 -0600279 pldmHandle->setTraceThrottle(false);
280 }
281#endif
Chris Cain7f89e4d2022-05-09 13:27:45 -0500282 if (waitingForAllOccActiveSensors)
283 {
284 log<level::INFO>(
285 "checkAllActiveSensors(): OCC Active sensors are available");
286 waitingForAllOccActiveSensors = false;
287 }
288 queuedActiveState.clear();
Chris Cainbae4d072022-02-28 09:46:50 -0600289 tracedSensorWait = false;
290 }
291 else
292 {
293 // Not all sensors were available, so keep waiting
294 if (!tracedSensorWait)
295 {
296 log<level::INFO>(
Chris Cainbd551de2022-04-26 13:41:16 -0500297 "checkAllActiveSensors(): Waiting for OCC Active sensors to become available");
Chris Cainbae4d072022-02-28 09:46:50 -0600298 tracedSensorWait = true;
299 }
Chris Cainf55f91a2022-05-27 13:40:15 -0500300 discoverTimer->restartOnce(10s);
Chris Cainbae4d072022-02-28 09:46:50 -0600301 }
302}
303#endif
304
Matt Spinlerd267cec2021-09-01 14:49:19 -0500305std::vector<int> Manager::findOCCsInDev()
306{
307 std::vector<int> occs;
308 std::regex expr{R"(occ(\d+)$)"};
309
310 for (auto& file : fs::directory_iterator("/dev"))
311 {
312 std::smatch match;
313 std::string path{file.path().string()};
314 if (std::regex_search(path, match, expr))
315 {
316 auto num = std::stoi(match[1].str());
317
318 // /dev numbering starts at 1, ours starts at 0.
319 occs.push_back(num - 1);
320 }
321 }
322
323 return occs;
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +0530324}
325
Patrick Williamsaf408082022-07-22 19:26:54 -0500326int Manager::cpuCreated(sdbusplus::message_t& msg)
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +0530327{
George Liubcef3b42021-09-10 12:39:02 +0800328 namespace fs = std::filesystem;
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +0530329
330 sdbusplus::message::object_path o;
331 msg.read(o);
332 fs::path cpuPath(std::string(std::move(o)));
333
334 auto name = cpuPath.filename().string();
335 auto index = name.find(CPU_NAME);
336 name.replace(index, std::strlen(CPU_NAME), OCC_NAME);
337
338 createObjects(name);
339
340 return 0;
341}
342
343void Manager::createObjects(const std::string& occ)
344{
345 auto path = fs::path(OCC_CONTROL_ROOT) / occ;
346
Gunnar Mills94df8c92018-09-14 14:50:03 -0500347 statusObjects.emplace_back(std::make_unique<Status>(
George Liuf3b75142021-06-10 11:22:50 +0800348 event, path.c_str(), *this,
Chris Cain36f9cde2021-11-22 11:18:21 -0600349#ifdef POWER10
350 pmode,
351#endif
Gunnar Mills94df8c92018-09-14 14:50:03 -0500352 std::bind(std::mem_fn(&Manager::statusCallBack), this,
Sheldon Bailey373af752022-02-21 15:14:00 -0600353 std::placeholders::_1, std::placeholders::_2)
Tom Joseph00325232020-07-29 17:51:48 +0530354#ifdef PLDM
355 ,
356 std::bind(std::mem_fn(&pldm::Interface::resetOCC), pldmHandle.get(),
357 std::placeholders::_1)
358#endif
359 ));
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +0530360
Chris Cain40501a22022-03-14 17:33:27 -0500361 // Create the power cap monitor object
362 if (!pcap)
363 {
364 pcap = std::make_unique<open_power::occ::powercap::PowerCap>(
365 *statusObjects.back());
366 }
367
Chris Cain36f9cde2021-11-22 11:18:21 -0600368 if (statusObjects.back()->isMasterOcc())
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +0530369 {
Chris Cain36f9cde2021-11-22 11:18:21 -0600370 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600371 std::format("Manager::createObjects(): OCC{} is the master",
Chris Cain36f9cde2021-11-22 11:18:21 -0600372 statusObjects.back()->getOccInstanceID())
373 .c_str());
374 _pollTimer->setEnabled(false);
375
Chris Cain78e86012021-03-04 16:15:31 -0600376#ifdef POWER10
Chris Cain6fa848a2022-01-24 14:54:38 -0600377 // Set the master OCC on the PowerMode object
378 pmode->setMasterOcc(path);
Chris Cain78e86012021-03-04 16:15:31 -0600379#endif
Chris Cain36f9cde2021-11-22 11:18:21 -0600380 }
381
382 passThroughObjects.emplace_back(std::make_unique<PassThrough>(path.c_str()
383#ifdef POWER10
384 ,
385 pmode
386#endif
387 ));
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +0530388}
389
Sheldon Bailey373af752022-02-21 15:14:00 -0600390void Manager::statusCallBack(instanceID instance, bool status)
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +0530391{
Chris Caina7b74dc2021-11-10 17:03:43 -0600392 if (status == true)
Eddie Jamesdae2d942017-12-20 10:50:03 -0600393 {
Chris Caina7b74dc2021-11-10 17:03:43 -0600394 // OCC went active
395 ++activeCount;
396
397#ifdef POWER10
398 if (activeCount == 1)
Eddie Jamesdae2d942017-12-20 10:50:03 -0600399 {
Chris Caina7b74dc2021-11-10 17:03:43 -0600400 // First OCC went active (allow some time for all OCCs to go active)
Chris Cainbd551de2022-04-26 13:41:16 -0500401 waitForAllOccsTimer->restartOnce(60s);
Matt Spinler53f68142021-08-25 15:47:31 -0500402 }
403#endif
Chris Caina7b74dc2021-11-10 17:03:43 -0600404
405 if (activeCount == statusObjects.size())
406 {
407#ifdef POWER10
408 // All OCCs are now running
409 if (waitForAllOccsTimer->isEnabled())
410 {
411 // stop occ wait timer
412 waitForAllOccsTimer->setEnabled(false);
413 }
414#endif
415
416 // Verify master OCC and start presence monitor
417 validateOccMaster();
418 }
419
420 // Start poll timer if not already started
421 if (!_pollTimer->isEnabled())
422 {
423 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600424 std::format("Manager: OCCs will be polled every {} seconds",
Chris Cain36f9cde2021-11-22 11:18:21 -0600425 pollInterval)
Chris Caina7b74dc2021-11-10 17:03:43 -0600426 .c_str());
427
428 // Send poll and start OCC poll timer
429 pollerTimerExpired();
430 }
431 }
432 else
433 {
434 // OCC went away
Chris Cain082a6ca2023-03-21 10:27:26 -0500435 if (activeCount > 0)
436 {
437 --activeCount;
438 }
439 else
440 {
441 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600442 std::format("OCC{} disabled, but currently no active OCCs",
Chris Cain082a6ca2023-03-21 10:27:26 -0500443 instance)
444 .c_str());
445 }
Chris Caina7b74dc2021-11-10 17:03:43 -0600446
447 if (activeCount == 0)
448 {
449 // No OCCs are running
450
451 // Stop OCC poll timer
452 if (_pollTimer->isEnabled())
453 {
454 log<level::INFO>(
455 "Manager::statusCallBack(): OCCs are not running, stopping poll timer");
456 _pollTimer->setEnabled(false);
457 }
458
459#ifdef POWER10
460 // stop wait timer
461 if (waitForAllOccsTimer->isEnabled())
462 {
463 waitForAllOccsTimer->setEnabled(false);
464 }
465#endif
Chris Caina7b74dc2021-11-10 17:03:43 -0600466 }
Sheldon Bailey373af752022-02-21 15:14:00 -0600467#ifdef READ_OCC_SENSORS
468 // Clear OCC sensors
Sheldon Baileyc8dd4592022-05-12 10:15:14 -0500469 setSensorValueToNaN(instance);
Sheldon Bailey373af752022-02-21 15:14:00 -0600470#endif
Chris Caina8857c52021-01-27 11:53:05 -0600471 }
Chris Cainbae4d072022-02-28 09:46:50 -0600472
473#ifdef POWER10
474 if (waitingForAllOccActiveSensors)
475 {
Chris Cain6d8f37a2022-04-29 13:46:01 -0500476 if (utils::isHostRunning())
477 {
478 checkAllActiveSensors();
479 }
Chris Cainbae4d072022-02-28 09:46:50 -0600480 }
481#endif
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +0530482}
483
484#ifdef I2C_OCC
485void Manager::initStatusObjects()
486{
487 // Make sure we have a valid path string
488 static_assert(sizeof(DEV_PATH) != 0);
489
490 auto deviceNames = i2c_occ::getOccHwmonDevices(DEV_PATH);
491 for (auto& name : deviceNames)
492 {
493 i2c_occ::i2cToDbus(name);
Lei YUb5259a12017-09-01 16:22:40 +0800494 name = std::string(OCC_NAME) + '_' + name;
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +0530495 auto path = fs::path(OCC_CONTROL_ROOT) / name;
496 statusObjects.emplace_back(
George Liuf3b75142021-06-10 11:22:50 +0800497 std::make_unique<Status>(event, path.c_str(), *this));
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +0530498 }
Chris Cain40501a22022-03-14 17:33:27 -0500499 // The first device is master occ
500 pcap = std::make_unique<open_power::occ::powercap::PowerCap>(
501 *statusObjects.front());
Chris Cain78e86012021-03-04 16:15:31 -0600502#ifdef POWER10
Chris Cain5d66a0a2022-02-09 08:52:10 -0600503 pmode = std::make_unique<powermode::PowerMode>(*this, powermode::PMODE_PATH,
504 powermode::PIPS_PATH);
Chris Cain6fa848a2022-01-24 14:54:38 -0600505 // Set the master OCC on the PowerMode object
506 pmode->setMasterOcc(path);
Chris Cain78e86012021-03-04 16:15:31 -0600507#endif
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +0530508}
509#endif
510
Tom Joseph815f9f52020-07-27 12:12:13 +0530511#ifdef PLDM
Eddie Jamescbad2192021-10-07 09:39:39 -0500512void Manager::sbeTimeout(unsigned int instance)
513{
Eddie James2a751d72022-03-04 09:16:12 -0600514 auto obj = std::find_if(statusObjects.begin(), statusObjects.end(),
515 [instance](const auto& obj) {
Patrick Williamsa49c9872023-05-10 07:50:35 -0500516 return instance == obj->getOccInstanceID();
517 });
Eddie Jamescbad2192021-10-07 09:39:39 -0500518
Eddie Jamescb018da2022-03-05 11:49:37 -0600519 if (obj != statusObjects.end() && (*obj)->occActive())
Eddie James2a751d72022-03-04 09:16:12 -0600520 {
Chris Cainbae4d072022-02-28 09:46:50 -0600521 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600522 std::format("SBE timeout, requesting HRESET (OCC{})", instance)
Chris Cainbae4d072022-02-28 09:46:50 -0600523 .c_str());
Eddie Jamescbad2192021-10-07 09:39:39 -0500524
Eddie James2a751d72022-03-04 09:16:12 -0600525 setSBEState(instance, SBE_STATE_NOT_USABLE);
526
527 pldmHandle->sendHRESET(instance);
528 }
Eddie Jamescbad2192021-10-07 09:39:39 -0500529}
530
Tom Joseph815f9f52020-07-27 12:12:13 +0530531bool Manager::updateOCCActive(instanceID instance, bool status)
532{
Chris Cain7e374fb2022-04-07 09:47:23 -0500533 auto obj = std::find_if(statusObjects.begin(), statusObjects.end(),
534 [instance](const auto& obj) {
Patrick Williamsa49c9872023-05-10 07:50:35 -0500535 return instance == obj->getOccInstanceID();
536 });
Chris Cain7e374fb2022-04-07 09:47:23 -0500537
Chris Cain082a6ca2023-03-21 10:27:26 -0500538 const bool hostRunning = open_power::occ::utils::isHostRunning();
Chris Cain7e374fb2022-04-07 09:47:23 -0500539 if (obj != statusObjects.end())
540 {
Chris Cain082a6ca2023-03-21 10:27:26 -0500541 if (!hostRunning && (status == true))
542 {
543 log<level::WARNING>(
Patrick Williams48002492024-02-13 21:43:32 -0600544 std::format(
Chris Cain082a6ca2023-03-21 10:27:26 -0500545 "updateOCCActive: Host is not running yet (OCC{} active={}), clearing sensor received",
546 instance, status)
547 .c_str());
548 (*obj)->setPldmSensorReceived(false);
549 if (!waitingForAllOccActiveSensors)
550 {
551 log<level::INFO>(
552 "updateOCCActive: Waiting for Host and all OCC Active Sensors");
553 waitingForAllOccActiveSensors = true;
554 }
Chris Cain755af102024-02-27 16:09:51 -0600555#ifdef POWER10
Chris Cain082a6ca2023-03-21 10:27:26 -0500556 discoverTimer->restartOnce(30s);
Chris Cain755af102024-02-27 16:09:51 -0600557#endif
Chris Cain082a6ca2023-03-21 10:27:26 -0500558 return false;
559 }
560 else
561 {
Patrick Williams48002492024-02-13 21:43:32 -0600562 log<level::INFO>(std::format("updateOCCActive: OCC{} active={}",
Chris Cain082a6ca2023-03-21 10:27:26 -0500563 instance, status)
564 .c_str());
565 (*obj)->setPldmSensorReceived(true);
566 return (*obj)->occActive(status);
567 }
Chris Cain7e374fb2022-04-07 09:47:23 -0500568 }
569 else
570 {
Chris Cain082a6ca2023-03-21 10:27:26 -0500571 if (hostRunning)
572 {
573 log<level::WARNING>(
Patrick Williams48002492024-02-13 21:43:32 -0600574 std::format(
Chris Cain082a6ca2023-03-21 10:27:26 -0500575 "updateOCCActive: No status object to update for OCC{} (active={})",
576 instance, status)
577 .c_str());
578 }
579 else
580 {
581 if (status == true)
582 {
583 log<level::WARNING>(
Patrick Williams48002492024-02-13 21:43:32 -0600584 std::format(
Chris Cain082a6ca2023-03-21 10:27:26 -0500585 "updateOCCActive: No status objects and Host is not running yet (OCC{} active={})",
586 instance, status)
587 .c_str());
588 }
589 }
Chris Cainbd551de2022-04-26 13:41:16 -0500590 if (status == true)
591 {
592 // OCC went active
593 queuedActiveState.insert(instance);
594 }
595 else
596 {
597 auto match = queuedActiveState.find(instance);
598 if (match != queuedActiveState.end())
599 {
600 // OCC was disabled
601 queuedActiveState.erase(match);
602 }
603 }
Chris Cain7e374fb2022-04-07 09:47:23 -0500604 return false;
605 }
Tom Joseph815f9f52020-07-27 12:12:13 +0530606}
Eddie Jamescbad2192021-10-07 09:39:39 -0500607
Sheldon Bailey31a2f132022-05-20 11:31:52 -0500608// Called upon pldm event To set powermode Safe Mode State for system.
609void Manager::updateOccSafeMode(bool safeMode)
610{
611#ifdef POWER10
612 pmode->updateDbusSafeMode(safeMode);
613#endif
Chris Cainc86d80f2023-05-04 15:49:18 -0500614 // Update the processor throttle status on dbus
615 for (auto& obj : statusObjects)
616 {
617 obj->updateThrottle(safeMode, THROTTLED_SAFE);
618 }
Sheldon Bailey31a2f132022-05-20 11:31:52 -0500619}
620
Eddie Jamescbad2192021-10-07 09:39:39 -0500621void Manager::sbeHRESETResult(instanceID instance, bool success)
622{
623 if (success)
624 {
Chris Cainbae4d072022-02-28 09:46:50 -0600625 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600626 std::format("HRESET succeeded (OCC{})", instance).c_str());
Eddie Jamescbad2192021-10-07 09:39:39 -0500627
628 setSBEState(instance, SBE_STATE_BOOTED);
629
630 return;
631 }
632
633 setSBEState(instance, SBE_STATE_FAILED);
634
635 if (sbeCanDump(instance))
636 {
Chris Cainbae4d072022-02-28 09:46:50 -0600637 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600638 std::format("HRESET failed (OCC{}), triggering SBE dump", instance)
Chris Cainbae4d072022-02-28 09:46:50 -0600639 .c_str());
Eddie Jamescbad2192021-10-07 09:39:39 -0500640
641 auto& bus = utils::getBus();
642 uint32_t src6 = instance << 16;
643 uint32_t logId =
644 FFDC::createPEL("org.open_power.Processor.Error.SbeChipOpTimeout",
645 src6, "SBE command timeout");
646
647 try
648 {
George Liuf3a4a692021-12-28 13:59:51 +0800649 constexpr auto interface = "xyz.openbmc_project.Dump.Create";
650 constexpr auto function = "CreateDump";
651
Dhruvaraj Subhashchandran1173b2b2024-06-01 11:12:13 -0500652 std::string service = utils::getService(OP_DUMP_OBJ_PATH,
653 interface);
654 auto method = bus.new_method_call(service.c_str(), OP_DUMP_OBJ_PATH,
655 interface, function);
Eddie Jamescbad2192021-10-07 09:39:39 -0500656
657 std::map<std::string, std::variant<std::string, uint64_t>>
658 createParams{
659 {"com.ibm.Dump.Create.CreateParameters.ErrorLogId",
660 uint64_t(logId)},
661 {"com.ibm.Dump.Create.CreateParameters.DumpType",
662 "com.ibm.Dump.Create.DumpType.SBE"},
663 {"com.ibm.Dump.Create.CreateParameters.FailingUnitId",
664 uint64_t(instance)},
665 };
666
667 method.append(createParams);
668
669 auto response = bus.call(method);
670 }
Patrick Williamsaf408082022-07-22 19:26:54 -0500671 catch (const sdbusplus::exception_t& e)
Eddie Jamescbad2192021-10-07 09:39:39 -0500672 {
673 constexpr auto ERROR_DUMP_DISABLED =
674 "xyz.openbmc_project.Dump.Create.Error.Disabled";
675 if (e.name() == ERROR_DUMP_DISABLED)
676 {
677 log<level::INFO>("Dump is disabled, skipping");
678 }
679 else
680 {
681 log<level::ERR>("Dump failed");
682 }
683 }
684 }
685}
686
687bool Manager::sbeCanDump(unsigned int instance)
688{
689 struct pdbg_target* proc = getPdbgTarget(instance);
690
691 if (!proc)
692 {
693 // allow the dump in the error case
694 return true;
695 }
696
697 try
698 {
699 if (!openpower::phal::sbe::isDumpAllowed(proc))
700 {
701 return false;
702 }
703
704 if (openpower::phal::pdbg::isSbeVitalAttnActive(proc))
705 {
706 return false;
707 }
708 }
709 catch (openpower::phal::exception::SbeError& e)
710 {
711 log<level::INFO>("Failed to query SBE state");
712 }
713
714 // allow the dump in the error case
715 return true;
716}
717
718void Manager::setSBEState(unsigned int instance, enum sbe_state state)
719{
720 struct pdbg_target* proc = getPdbgTarget(instance);
721
722 if (!proc)
723 {
724 return;
725 }
726
727 try
728 {
729 openpower::phal::sbe::setState(proc, state);
730 }
731 catch (const openpower::phal::exception::SbeError& e)
732 {
733 log<level::ERR>("Failed to set SBE state");
734 }
735}
736
737struct pdbg_target* Manager::getPdbgTarget(unsigned int instance)
738{
739 if (!pdbgInitialized)
740 {
741 try
742 {
743 openpower::phal::pdbg::init();
744 pdbgInitialized = true;
745 }
746 catch (const openpower::phal::exception::PdbgError& e)
747 {
748 log<level::ERR>("pdbg initialization failed");
749 return nullptr;
750 }
751 }
752
753 struct pdbg_target* proc = nullptr;
754 pdbg_for_each_class_target("proc", proc)
755 {
756 if (pdbg_target_index(proc) == instance)
757 {
758 return proc;
759 }
760 }
761
762 log<level::ERR>("Failed to get pdbg target");
763 return nullptr;
764}
Tom Joseph815f9f52020-07-27 12:12:13 +0530765#endif
766
Chris Caina8857c52021-01-27 11:53:05 -0600767void Manager::pollerTimerExpired()
768{
Chris Caina8857c52021-01-27 11:53:05 -0600769 if (!_pollTimer)
770 {
771 log<level::ERR>(
772 "Manager::pollerTimerExpired() ERROR: Timer not defined");
773 return;
774 }
775
776 for (auto& obj : statusObjects)
777 {
Chris Caina7b74dc2021-11-10 17:03:43 -0600778 if (!obj->occActive())
779 {
780 // OCC is not running yet
781#ifdef READ_OCC_SENSORS
Chris Cain5d66a0a2022-02-09 08:52:10 -0600782 auto id = obj->getOccInstanceID();
Sheldon Baileyc8dd4592022-05-12 10:15:14 -0500783 setSensorValueToNaN(id);
Chris Caina7b74dc2021-11-10 17:03:43 -0600784#endif
785 continue;
786 }
787
Chris Caina8857c52021-01-27 11:53:05 -0600788 // Read sysfs to force kernel to poll OCC
789 obj->readOccState();
Chicago Duanbb895cb2021-06-18 19:37:16 +0800790
791#ifdef READ_OCC_SENSORS
792 // Read occ sensor values
Chris Cain5d66a0a2022-02-09 08:52:10 -0600793 getSensorValues(obj);
Chicago Duanbb895cb2021-06-18 19:37:16 +0800794#endif
Chris Caina8857c52021-01-27 11:53:05 -0600795 }
796
Chris Caina7b74dc2021-11-10 17:03:43 -0600797 if (activeCount > 0)
798 {
799 // Restart OCC poll timer
800 _pollTimer->restartOnce(std::chrono::seconds(pollInterval));
801 }
802 else
803 {
804 // No OCCs running, so poll timer will not be restarted
805 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -0600806 std::format(
Chris Caina7b74dc2021-11-10 17:03:43 -0600807 "Manager::pollerTimerExpired: poll timer will not be restarted")
808 .c_str());
809 }
Chris Caina8857c52021-01-27 11:53:05 -0600810}
811
Chicago Duanbb895cb2021-06-18 19:37:16 +0800812#ifdef READ_OCC_SENSORS
Chris Cainae157b62024-01-23 16:05:12 -0600813void Manager::readTempSensors(const fs::path& path, uint32_t occInstance)
Chicago Duanbb895cb2021-06-18 19:37:16 +0800814{
Matt Spinler818cc8d2023-10-23 11:43:39 -0500815 // There may be more than one sensor with the same FRU type
816 // and label so make two passes: the first to read the temps
817 // from sysfs, and the second to put them on D-Bus after
818 // resolving any conflicts.
819 std::map<std::string, double> sensorData;
820
Chicago Duanbb895cb2021-06-18 19:37:16 +0800821 std::regex expr{"temp\\d+_label$"}; // Example: temp5_label
822 for (auto& file : fs::directory_iterator(path))
823 {
824 if (!std::regex_search(file.path().string(), expr))
825 {
826 continue;
827 }
Chicago Duanbb895cb2021-06-18 19:37:16 +0800828
Matt Spinlera26f1522021-08-25 15:50:20 -0500829 uint32_t labelValue{0};
830
831 try
832 {
833 labelValue = readFile<uint32_t>(file.path());
834 }
835 catch (const std::system_error& e)
836 {
837 log<level::DEBUG>(
Patrick Williams48002492024-02-13 21:43:32 -0600838 std::format("readTempSensors: Failed reading {}, errno = {}",
Matt Spinlera26f1522021-08-25 15:50:20 -0500839 file.path().string(), e.code().value())
840 .c_str());
Chicago Duanbb895cb2021-06-18 19:37:16 +0800841 continue;
842 }
Chicago Duanbb895cb2021-06-18 19:37:16 +0800843
844 const std::string& tempLabel = "label";
845 const std::string filePathString = file.path().string().substr(
846 0, file.path().string().length() - tempLabel.length());
Matt Spinlera26f1522021-08-25 15:50:20 -0500847
848 uint32_t fruTypeValue{0};
849 try
Chicago Duanbb895cb2021-06-18 19:37:16 +0800850 {
Matt Spinlera26f1522021-08-25 15:50:20 -0500851 fruTypeValue = readFile<uint32_t>(filePathString + fruTypeSuffix);
852 }
853 catch (const std::system_error& e)
854 {
Chicago Duanbb895cb2021-06-18 19:37:16 +0800855 log<level::DEBUG>(
Patrick Williams48002492024-02-13 21:43:32 -0600856 std::format("readTempSensors: Failed reading {}, errno = {}",
Matt Spinlera26f1522021-08-25 15:50:20 -0500857 filePathString + fruTypeSuffix, e.code().value())
Chicago Duanbb895cb2021-06-18 19:37:16 +0800858 .c_str());
859 continue;
860 }
Chicago Duanbb895cb2021-06-18 19:37:16 +0800861
Patrick Williamsa49c9872023-05-10 07:50:35 -0500862 std::string sensorPath = OCC_SENSORS_ROOT +
863 std::string("/temperature/");
Chicago Duanbb895cb2021-06-18 19:37:16 +0800864
Matt Spinlerace67d82021-10-18 13:41:57 -0500865 std::string dvfsTempPath;
866
Chicago Duanbb895cb2021-06-18 19:37:16 +0800867 if (fruTypeValue == VRMVdd)
868 {
Chris Cainae157b62024-01-23 16:05:12 -0600869 sensorPath.append("vrm_vdd" + std::to_string(occInstance) +
870 "_temp");
Chicago Duanbb895cb2021-06-18 19:37:16 +0800871 }
Matt Spinlerace67d82021-10-18 13:41:57 -0500872 else if (fruTypeValue == processorIoRing)
873 {
Chris Cainae157b62024-01-23 16:05:12 -0600874 sensorPath.append("proc" + std::to_string(occInstance) +
875 "_ioring_temp");
Matt Spinlerace67d82021-10-18 13:41:57 -0500876 dvfsTempPath = std::string{OCC_SENSORS_ROOT} + "/temperature/proc" +
Chris Cainae157b62024-01-23 16:05:12 -0600877 std::to_string(occInstance) + "_ioring_dvfs_temp";
Matt Spinlerace67d82021-10-18 13:41:57 -0500878 }
Chicago Duanbb895cb2021-06-18 19:37:16 +0800879 else
880 {
Matt Spinler14d14022021-08-25 15:38:29 -0500881 uint16_t type = (labelValue & 0xFF000000) >> 24;
882 uint16_t instanceID = labelValue & 0x0000FFFF;
Chicago Duanbb895cb2021-06-18 19:37:16 +0800883
884 if (type == OCC_DIMM_TEMP_SENSOR_TYPE)
885 {
Matt Spinler8b8abee2021-08-25 15:18:21 -0500886 if (fruTypeValue == fruTypeNotAvailable)
887 {
888 // Not all DIMM related temps are available to read
889 // (no _input file in this case)
890 continue;
891 }
Chicago Duanbb895cb2021-06-18 19:37:16 +0800892 auto iter = dimmTempSensorName.find(fruTypeValue);
893 if (iter == dimmTempSensorName.end())
894 {
George Liub5ca1012021-09-10 12:53:11 +0800895 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -0600896 std::format(
George Liub5ca1012021-09-10 12:53:11 +0800897 "readTempSensors: Fru type error! fruTypeValue = {}) ",
898 fruTypeValue)
899 .c_str());
Chicago Duanbb895cb2021-06-18 19:37:16 +0800900 continue;
901 }
902
903 sensorPath.append("dimm" + std::to_string(instanceID) +
904 iter->second);
Matt Spinlerad8f4522023-10-25 11:14:46 -0500905
906 dvfsTempPath = std::string{OCC_SENSORS_ROOT} + "/temperature/" +
907 dimmDVFSSensorName.at(fruTypeValue);
Chicago Duanbb895cb2021-06-18 19:37:16 +0800908 }
909 else if (type == OCC_CPU_TEMP_SENSOR_TYPE)
910 {
Matt Spinlerace67d82021-10-18 13:41:57 -0500911 if (fruTypeValue == processorCore)
Chicago Duanbb895cb2021-06-18 19:37:16 +0800912 {
Matt Spinlerace67d82021-10-18 13:41:57 -0500913 // The OCC reports small core temps, of which there are
914 // two per big core. All current P10 systems are in big
915 // core mode, so use a big core name.
916 uint16_t coreNum = instanceID / 2;
917 uint16_t tempNum = instanceID % 2;
Chris Cainae157b62024-01-23 16:05:12 -0600918 sensorPath.append("proc" + std::to_string(occInstance) +
919 "_core" + std::to_string(coreNum) + "_" +
Matt Spinlerace67d82021-10-18 13:41:57 -0500920 std::to_string(tempNum) + "_temp");
921
Chris Cainae157b62024-01-23 16:05:12 -0600922 dvfsTempPath =
923 std::string{OCC_SENSORS_ROOT} + "/temperature/proc" +
924 std::to_string(occInstance) + "_core_dvfs_temp";
Matt Spinlerace67d82021-10-18 13:41:57 -0500925 }
926 else
927 {
Chicago Duanbb895cb2021-06-18 19:37:16 +0800928 continue;
929 }
Chicago Duanbb895cb2021-06-18 19:37:16 +0800930 }
931 else
932 {
933 continue;
934 }
935 }
936
Matt Spinlerace67d82021-10-18 13:41:57 -0500937 // The dvfs temp file only needs to be read once per chip per type.
938 if (!dvfsTempPath.empty() &&
939 !dbus::OccDBusSensors::getOccDBus().hasDvfsTemp(dvfsTempPath))
940 {
941 try
942 {
943 auto dvfsValue = readFile<double>(filePathString + maxSuffix);
944
945 dbus::OccDBusSensors::getOccDBus().setDvfsTemp(
946 dvfsTempPath, dvfsValue * std::pow(10, -3));
947 }
948 catch (const std::system_error& e)
949 {
950 log<level::DEBUG>(
Patrick Williams48002492024-02-13 21:43:32 -0600951 std::format(
Matt Spinlerace67d82021-10-18 13:41:57 -0500952 "readTempSensors: Failed reading {}, errno = {}",
953 filePathString + maxSuffix, e.code().value())
954 .c_str());
955 }
956 }
957
Matt Spinlera26f1522021-08-25 15:50:20 -0500958 uint32_t faultValue{0};
959 try
Chicago Duanbb895cb2021-06-18 19:37:16 +0800960 {
Matt Spinlera26f1522021-08-25 15:50:20 -0500961 faultValue = readFile<uint32_t>(filePathString + faultSuffix);
962 }
963 catch (const std::system_error& e)
964 {
965 log<level::DEBUG>(
Patrick Williams48002492024-02-13 21:43:32 -0600966 std::format("readTempSensors: Failed reading {}, errno = {}",
Matt Spinlera26f1522021-08-25 15:50:20 -0500967 filePathString + faultSuffix, e.code().value())
968 .c_str());
969 continue;
Chicago Duanbb895cb2021-06-18 19:37:16 +0800970 }
971
Chris Cainae157b62024-01-23 16:05:12 -0600972 double tempValue{0};
973 // NOTE: if OCC sends back 0xFF, kernal sets this fault value to 1.
Matt Spinlera26f1522021-08-25 15:50:20 -0500974 if (faultValue != 0)
Chicago Duanbb895cb2021-06-18 19:37:16 +0800975 {
Chris Cainae157b62024-01-23 16:05:12 -0600976 tempValue = std::numeric_limits<double>::quiet_NaN();
Chicago Duanbb895cb2021-06-18 19:37:16 +0800977 }
Chris Cainae157b62024-01-23 16:05:12 -0600978 else
Chicago Duanbb895cb2021-06-18 19:37:16 +0800979 {
Chris Cainae157b62024-01-23 16:05:12 -0600980 // Read the temperature
981 try
Sheldon Baileycd0940b2022-04-26 14:24:05 -0500982 {
Chris Cainae157b62024-01-23 16:05:12 -0600983 tempValue = readFile<double>(filePathString + inputSuffix);
Sheldon Baileycd0940b2022-04-26 14:24:05 -0500984 }
Chris Cainae157b62024-01-23 16:05:12 -0600985 catch (const std::system_error& e)
Sheldon Baileycd0940b2022-04-26 14:24:05 -0500986 {
Chris Cainae157b62024-01-23 16:05:12 -0600987 log<level::DEBUG>(
Patrick Williams48002492024-02-13 21:43:32 -0600988 std::format(
Chris Cainae157b62024-01-23 16:05:12 -0600989 "readTempSensors: Failed reading {}, errno = {}",
990 filePathString + inputSuffix, e.code().value())
991 .c_str());
992
993 // if errno == EAGAIN(Resource temporarily unavailable) then set
994 // temp to 0, to avoid using old temp, and affecting FAN
995 // Control.
996 if (e.code().value() == EAGAIN)
997 {
998 tempValue = 0;
999 }
1000 // else the errno would be something like
1001 // EBADF(Bad file descriptor)
1002 // or ENOENT(No such file or directory)
1003 else
1004 {
1005 continue;
1006 }
Sheldon Baileycd0940b2022-04-26 14:24:05 -05001007 }
Matt Spinlera26f1522021-08-25 15:50:20 -05001008 }
1009
Matt Spinler818cc8d2023-10-23 11:43:39 -05001010 // If this object path already has a value, only overwite
1011 // it if the previous one was an NaN or a smaller value.
1012 auto existing = sensorData.find(sensorPath);
1013 if (existing != sensorData.end())
1014 {
Chris Cainae157b62024-01-23 16:05:12 -06001015 // Multiple sensors found for this FRU type
1016 if ((std::isnan(existing->second) && (tempValue == 0)) ||
1017 ((existing->second == 0) && std::isnan(tempValue)))
1018 {
1019 // One of the redundant sensors has failed (0xFF/nan), and the
1020 // other sensor has no reading (0), so set the FRU to NaN to
1021 // force fan increase
1022 tempValue = std::numeric_limits<double>::quiet_NaN();
1023 existing->second = tempValue;
1024 }
Matt Spinler818cc8d2023-10-23 11:43:39 -05001025 if (std::isnan(existing->second) || (tempValue > existing->second))
1026 {
1027 existing->second = tempValue;
1028 }
1029 }
1030 else
1031 {
Chris Cainae157b62024-01-23 16:05:12 -06001032 // First sensor for this FRU type
Matt Spinler818cc8d2023-10-23 11:43:39 -05001033 sensorData[sensorPath] = tempValue;
1034 }
1035 }
Matt Spinlera26f1522021-08-25 15:50:20 -05001036
Matt Spinler818cc8d2023-10-23 11:43:39 -05001037 // Now publish the values on D-Bus.
1038 for (const auto& [objectPath, value] : sensorData)
1039 {
1040 dbus::OccDBusSensors::getOccDBus().setValue(objectPath,
1041 value * std::pow(10, -3));
Matt Spinlera26f1522021-08-25 15:50:20 -05001042
Matt Spinler818cc8d2023-10-23 11:43:39 -05001043 dbus::OccDBusSensors::getOccDBus().setOperationalStatus(
1044 objectPath, !std::isnan(value));
1045
1046 if (existingSensors.find(objectPath) == existingSensors.end())
Chris Cain6fa848a2022-01-24 14:54:38 -06001047 {
Chris Cain5d66a0a2022-02-09 08:52:10 -06001048 dbus::OccDBusSensors::getOccDBus().setChassisAssociation(
Matt Spinler818cc8d2023-10-23 11:43:39 -05001049 objectPath);
Chris Cain6fa848a2022-01-24 14:54:38 -06001050 }
1051
Chris Cainae157b62024-01-23 16:05:12 -06001052 existingSensors[objectPath] = occInstance;
Chicago Duanbb895cb2021-06-18 19:37:16 +08001053 }
Chicago Duanbb895cb2021-06-18 19:37:16 +08001054}
1055
1056std::optional<std::string>
1057 Manager::getPowerLabelFunctionID(const std::string& value)
1058{
1059 // If the value is "system", then the FunctionID is "system".
1060 if (value == "system")
1061 {
1062 return value;
1063 }
1064
1065 // If the value is not "system", then the label value have 3 numbers, of
1066 // which we only care about the middle one:
1067 // <sensor id>_<function id>_<apss channel>
1068 // eg: The value is "0_10_5" , then the FunctionID is "10".
1069 if (value.find("_") == std::string::npos)
1070 {
1071 return std::nullopt;
1072 }
1073
1074 auto powerLabelValue = value.substr((value.find("_") + 1));
1075
1076 if (powerLabelValue.find("_") == std::string::npos)
1077 {
1078 return std::nullopt;
1079 }
1080
1081 return powerLabelValue.substr(0, powerLabelValue.find("_"));
1082}
1083
1084void Manager::readPowerSensors(const fs::path& path, uint32_t id)
1085{
Chicago Duanbb895cb2021-06-18 19:37:16 +08001086 std::regex expr{"power\\d+_label$"}; // Example: power5_label
1087 for (auto& file : fs::directory_iterator(path))
1088 {
1089 if (!std::regex_search(file.path().string(), expr))
1090 {
1091 continue;
1092 }
Chicago Duanbb895cb2021-06-18 19:37:16 +08001093
Matt Spinlera26f1522021-08-25 15:50:20 -05001094 std::string labelValue;
1095 try
1096 {
1097 labelValue = readFile<std::string>(file.path());
1098 }
1099 catch (const std::system_error& e)
1100 {
1101 log<level::DEBUG>(
Patrick Williams48002492024-02-13 21:43:32 -06001102 std::format("readPowerSensors: Failed reading {}, errno = {}",
Matt Spinlera26f1522021-08-25 15:50:20 -05001103 file.path().string(), e.code().value())
1104 .c_str());
Chicago Duanbb895cb2021-06-18 19:37:16 +08001105 continue;
1106 }
Chicago Duanbb895cb2021-06-18 19:37:16 +08001107
1108 auto functionID = getPowerLabelFunctionID(labelValue);
1109 if (functionID == std::nullopt)
1110 {
1111 continue;
1112 }
1113
1114 const std::string& tempLabel = "label";
1115 const std::string filePathString = file.path().string().substr(
1116 0, file.path().string().length() - tempLabel.length());
1117
1118 std::string sensorPath = OCC_SENSORS_ROOT + std::string("/power/");
1119
1120 auto iter = powerSensorName.find(*functionID);
1121 if (iter == powerSensorName.end())
1122 {
1123 continue;
1124 }
1125 sensorPath.append(iter->second);
1126
Matt Spinlera26f1522021-08-25 15:50:20 -05001127 double tempValue{0};
1128
1129 try
Chicago Duanbb895cb2021-06-18 19:37:16 +08001130 {
Matt Spinlera26f1522021-08-25 15:50:20 -05001131 tempValue = readFile<double>(filePathString + inputSuffix);
Chicago Duanbb895cb2021-06-18 19:37:16 +08001132 }
Matt Spinlera26f1522021-08-25 15:50:20 -05001133 catch (const std::system_error& e)
Chicago Duanbb895cb2021-06-18 19:37:16 +08001134 {
Chicago Duanbb895cb2021-06-18 19:37:16 +08001135 log<level::DEBUG>(
Patrick Williams48002492024-02-13 21:43:32 -06001136 std::format("readPowerSensors: Failed reading {}, errno = {}",
Matt Spinlera26f1522021-08-25 15:50:20 -05001137 filePathString + inputSuffix, e.code().value())
Chicago Duanbb895cb2021-06-18 19:37:16 +08001138 .c_str());
Matt Spinlera26f1522021-08-25 15:50:20 -05001139 continue;
Chicago Duanbb895cb2021-06-18 19:37:16 +08001140 }
Matt Spinlera26f1522021-08-25 15:50:20 -05001141
Chris Cain5d66a0a2022-02-09 08:52:10 -06001142 dbus::OccDBusSensors::getOccDBus().setUnit(
Chris Caind84a8332022-01-13 08:58:45 -06001143 sensorPath, "xyz.openbmc_project.Sensor.Value.Unit.Watts");
1144
Chris Cain5d66a0a2022-02-09 08:52:10 -06001145 dbus::OccDBusSensors::getOccDBus().setValue(
Matt Spinlera26f1522021-08-25 15:50:20 -05001146 sensorPath, tempValue * std::pow(10, -3) * std::pow(10, -3));
1147
Chris Cain5d66a0a2022-02-09 08:52:10 -06001148 dbus::OccDBusSensors::getOccDBus().setOperationalStatus(sensorPath,
1149 true);
Matt Spinlera26f1522021-08-25 15:50:20 -05001150
Matt Spinler5901abd2021-09-23 13:50:03 -05001151 if (existingSensors.find(sensorPath) == existingSensors.end())
1152 {
Chris Cain5d66a0a2022-02-09 08:52:10 -06001153 dbus::OccDBusSensors::getOccDBus().setChassisAssociation(
1154 sensorPath);
Matt Spinler5901abd2021-09-23 13:50:03 -05001155 }
1156
Matt Spinlera26f1522021-08-25 15:50:20 -05001157 existingSensors[sensorPath] = id;
Chicago Duanbb895cb2021-06-18 19:37:16 +08001158 }
1159 return;
1160}
1161
Sheldon Baileyc8dd4592022-05-12 10:15:14 -05001162void Manager::setSensorValueToNaN(uint32_t id) const
Chicago Duanbb895cb2021-06-18 19:37:16 +08001163{
1164 for (const auto& [sensorPath, occId] : existingSensors)
1165 {
1166 if (occId == id)
1167 {
Chris Cain5d66a0a2022-02-09 08:52:10 -06001168 dbus::OccDBusSensors::getOccDBus().setValue(
Chicago Duanbb895cb2021-06-18 19:37:16 +08001169 sensorPath, std::numeric_limits<double>::quiet_NaN());
Sheldon Baileyc8dd4592022-05-12 10:15:14 -05001170
1171 dbus::OccDBusSensors::getOccDBus().setOperationalStatus(sensorPath,
1172 true);
Chicago Duanbb895cb2021-06-18 19:37:16 +08001173 }
1174 }
1175 return;
1176}
1177
Sheldon Bailey373af752022-02-21 15:14:00 -06001178void Manager::setSensorValueToNonFunctional(uint32_t id) const
1179{
1180 for (const auto& [sensorPath, occId] : existingSensors)
1181 {
1182 if (occId == id)
1183 {
1184 dbus::OccDBusSensors::getOccDBus().setValue(
1185 sensorPath, std::numeric_limits<double>::quiet_NaN());
1186
1187 dbus::OccDBusSensors::getOccDBus().setOperationalStatus(sensorPath,
1188 false);
1189 }
1190 }
1191 return;
1192}
1193
Chris Cain5d66a0a2022-02-09 08:52:10 -06001194void Manager::getSensorValues(std::unique_ptr<Status>& occ)
Chicago Duanbb895cb2021-06-18 19:37:16 +08001195{
Chris Caine2d0a432022-03-28 11:08:49 -05001196 static bool tracedError[8] = {0};
1197 const fs::path sensorPath = occ->getHwmonPath();
Chris Cain5d66a0a2022-02-09 08:52:10 -06001198 const uint32_t id = occ->getOccInstanceID();
Chicago Duanbb895cb2021-06-18 19:37:16 +08001199
Chris Caine2d0a432022-03-28 11:08:49 -05001200 if (fs::exists(sensorPath))
Chicago Duanbb895cb2021-06-18 19:37:16 +08001201 {
Chris Caine2d0a432022-03-28 11:08:49 -05001202 // Read temperature sensors
1203 readTempSensors(sensorPath, id);
1204
1205 if (occ->isMasterOcc())
1206 {
1207 // Read power sensors
1208 readPowerSensors(sensorPath, id);
1209 }
1210 tracedError[id] = false;
1211 }
1212 else
1213 {
1214 if (!tracedError[id])
1215 {
1216 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -06001217 std::format(
Chris Caine2d0a432022-03-28 11:08:49 -05001218 "Manager::getSensorValues: OCC{} sensor path missing: {}",
1219 id, sensorPath.c_str())
1220 .c_str());
1221 tracedError[id] = true;
1222 }
Chicago Duanbb895cb2021-06-18 19:37:16 +08001223 }
1224
1225 return;
1226}
1227#endif
Chris Cain17257672021-10-22 13:41:03 -05001228
1229// Read the altitude from DBus
1230void Manager::readAltitude()
1231{
1232 static bool traceAltitudeErr = true;
1233
1234 utils::PropertyValue altitudeProperty{};
1235 try
1236 {
1237 altitudeProperty = utils::getProperty(ALTITUDE_PATH, ALTITUDE_INTERFACE,
1238 ALTITUDE_PROP);
1239 auto sensorVal = std::get<double>(altitudeProperty);
1240 if (sensorVal < 0xFFFF)
1241 {
1242 if (sensorVal < 0)
1243 {
1244 altitude = 0;
1245 }
1246 else
1247 {
1248 // Round to nearest meter
1249 altitude = uint16_t(sensorVal + 0.5);
1250 }
Patrick Williams48002492024-02-13 21:43:32 -06001251 log<level::DEBUG>(std::format("readAltitude: sensor={} ({}m)",
Chris Cain17257672021-10-22 13:41:03 -05001252 sensorVal, altitude)
1253 .c_str());
1254 traceAltitudeErr = true;
1255 }
1256 else
1257 {
1258 if (traceAltitudeErr)
1259 {
1260 traceAltitudeErr = false;
1261 log<level::DEBUG>(
Patrick Williams48002492024-02-13 21:43:32 -06001262 std::format("Invalid altitude value: {}", sensorVal)
Chris Cain17257672021-10-22 13:41:03 -05001263 .c_str());
1264 }
1265 }
1266 }
Patrick Williamsaf408082022-07-22 19:26:54 -05001267 catch (const sdbusplus::exception_t& e)
Chris Cain17257672021-10-22 13:41:03 -05001268 {
1269 if (traceAltitudeErr)
1270 {
1271 traceAltitudeErr = false;
1272 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -06001273 std::format("Unable to read Altitude: {}", e.what()).c_str());
Chris Cain17257672021-10-22 13:41:03 -05001274 }
1275 altitude = 0xFFFF; // not available
1276 }
1277}
1278
1279// Callback function when ambient temperature changes
Patrick Williamsaf408082022-07-22 19:26:54 -05001280void Manager::ambientCallback(sdbusplus::message_t& msg)
Chris Cain17257672021-10-22 13:41:03 -05001281{
1282 double currentTemp = 0;
1283 uint8_t truncatedTemp = 0xFF;
1284 std::string msgSensor;
1285 std::map<std::string, std::variant<double>> msgData;
1286 msg.read(msgSensor, msgData);
1287
1288 auto valPropMap = msgData.find(AMBIENT_PROP);
1289 if (valPropMap == msgData.end())
1290 {
1291 log<level::DEBUG>("ambientCallback: Unknown ambient property changed");
1292 return;
1293 }
1294 currentTemp = std::get<double>(valPropMap->second);
1295 if (std::isnan(currentTemp))
1296 {
1297 truncatedTemp = 0xFF;
1298 }
1299 else
1300 {
1301 if (currentTemp < 0)
1302 {
1303 truncatedTemp = 0;
1304 }
1305 else
1306 {
1307 // Round to nearest degree C
1308 truncatedTemp = uint8_t(currentTemp + 0.5);
1309 }
1310 }
1311
1312 // If ambient changes, notify OCCs
1313 if (truncatedTemp != ambient)
1314 {
1315 log<level::DEBUG>(
Patrick Williams48002492024-02-13 21:43:32 -06001316 std::format("ambientCallback: Ambient change from {} to {}C",
Chris Cain17257672021-10-22 13:41:03 -05001317 ambient, currentTemp)
1318 .c_str());
1319
1320 ambient = truncatedTemp;
1321 if (altitude == 0xFFFF)
1322 {
1323 // No altitude yet, try reading again
1324 readAltitude();
1325 }
1326
1327 log<level::DEBUG>(
Patrick Williams48002492024-02-13 21:43:32 -06001328 std::format("ambientCallback: Ambient: {}C, altitude: {}m", ambient,
Chris Cain17257672021-10-22 13:41:03 -05001329 altitude)
1330 .c_str());
1331#ifdef POWER10
1332 // Send ambient and altitude to all OCCs
1333 for (auto& obj : statusObjects)
1334 {
1335 if (obj->occActive())
1336 {
1337 obj->sendAmbient(ambient, altitude);
1338 }
1339 }
1340#endif // POWER10
1341 }
1342}
1343
1344// return the current ambient and altitude readings
1345void Manager::getAmbientData(bool& ambientValid, uint8_t& ambientTemp,
1346 uint16_t& altitudeValue) const
1347{
1348 ambientValid = true;
1349 ambientTemp = ambient;
1350 altitudeValue = altitude;
1351
1352 if (ambient == 0xFF)
1353 {
1354 ambientValid = false;
1355 }
1356}
1357
Chris Caina7b74dc2021-11-10 17:03:43 -06001358#ifdef POWER10
Chris Cain7f89e4d2022-05-09 13:27:45 -05001359// Called when waitForAllOccsTimer expires
1360// After the first OCC goes active, this timer will be started (60 seconds)
Chris Caina7b74dc2021-11-10 17:03:43 -06001361void Manager::occsNotAllRunning()
1362{
Chris Caina7b74dc2021-11-10 17:03:43 -06001363 if (activeCount != statusObjects.size())
1364 {
1365 // Not all OCCs went active
1366 log<level::WARNING>(
Patrick Williams48002492024-02-13 21:43:32 -06001367 std::format(
Chris Caina7b74dc2021-11-10 17:03:43 -06001368 "occsNotAllRunning: Active OCC count ({}) does not match expected count ({})",
1369 activeCount, statusObjects.size())
1370 .c_str());
Chris Cain7f89e4d2022-05-09 13:27:45 -05001371 // Procs may be garded, so may be expected
Chris Caina7b74dc2021-11-10 17:03:43 -06001372 }
1373
1374 validateOccMaster();
1375}
Chris Cain755af102024-02-27 16:09:51 -06001376
1377#ifdef PLDM
Chris Cainc33171b2024-05-24 16:14:50 -05001378// Called when throttlePldmTraceTimer expires.
Chris Caina19bd422024-05-24 16:39:01 -05001379// If this timer expires, that indicates there are no OCC active sensor PDRs
Chris Cainc33171b2024-05-24 16:14:50 -05001380// found which will trigger pldm traces to be throttled.
1381// The second time this timer expires, a PEL will get created.
1382void Manager::throttlePldmTraceExpired()
Chris Cain755af102024-02-27 16:09:51 -06001383{
Chris Cain7651c062024-05-02 14:14:06 -05001384 if (utils::isHostRunning())
1385 {
Chris Cainc33171b2024-05-24 16:14:50 -05001386 if (!onPldmTimeoutCreatePel)
1387 {
1388 // Throttle traces
1389 pldmHandle->setTraceThrottle(true);
1390 // Restart timer to log a PEL when timer expires
1391 onPldmTimeoutCreatePel = true;
1392 throttlePldmTraceTimer->restartOnce(40min);
1393 }
1394 else
1395 {
1396 log<level::ERR>(
1397 "throttlePldmTraceExpired(): OCC active sensors still not available!");
1398 // Create PEL
1399 createPldmSensorPEL();
1400 }
Chris Cain7651c062024-05-02 14:14:06 -05001401 }
1402 else
1403 {
1404 // Make sure traces are not throttled
1405 pldmHandle->setTraceThrottle(false);
1406 log<level::INFO>(
Chris Cainc33171b2024-05-24 16:14:50 -05001407 "throttlePldmTraceExpired(): host it not running ignoring sensor timer");
Chris Cain7651c062024-05-02 14:14:06 -05001408 }
Chris Cain4b82f3e2024-04-22 14:44:29 -05001409}
1410
1411void Manager::createPldmSensorPEL()
1412{
1413 Error::Descriptor d = Error::Descriptor(MISSING_OCC_SENSORS_PATH);
1414 std::map<std::string, std::string> additionalData;
1415
1416 additionalData.emplace("_PID", std::to_string(getpid()));
1417
1418 log<level::INFO>(
1419 std::format(
1420 "createPldmSensorPEL(): Unable to find PLDM sensors for the OCCs")
1421 .c_str());
1422
1423 auto& bus = utils::getBus();
1424
1425 try
1426 {
1427 FFDCFiles ffdc;
1428 // Add occ-control journal traces to PEL FFDC
1429 auto occJournalFile =
1430 FFDC::addJournalEntries(ffdc, "openpower-occ-control", 40);
1431
1432 static constexpr auto loggingObjectPath =
1433 "/xyz/openbmc_project/logging";
1434 static constexpr auto opLoggingInterface = "org.open_power.Logging.PEL";
1435 std::string service = utils::getService(loggingObjectPath,
1436 opLoggingInterface);
1437 auto method = bus.new_method_call(service.c_str(), loggingObjectPath,
1438 opLoggingInterface,
1439 "CreatePELWithFFDCFiles");
1440
Chris Cain1c3349e2024-04-24 14:14:11 -05001441 // Set level to Warning (Predictive).
Chris Cain4b82f3e2024-04-22 14:44:29 -05001442 auto level =
1443 sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage(
1444 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level::
Chris Cain1c3349e2024-04-24 14:14:11 -05001445 Warning);
Chris Cain4b82f3e2024-04-22 14:44:29 -05001446
1447 method.append(d.path, level, additionalData, ffdc);
1448 bus.call(method);
1449 }
1450 catch (const sdbusplus::exception_t& e)
1451 {
1452 log<level::ERR>(
1453 std::format("Failed to create MISSING_OCC_SENSORS PEL: {}",
1454 e.what())
1455 .c_str());
1456 }
Chris Cain755af102024-02-27 16:09:51 -06001457}
1458#endif // PLDM
Chris Caina7b74dc2021-11-10 17:03:43 -06001459#endif // POWER10
1460
1461// Verify single master OCC and start presence monitor
1462void Manager::validateOccMaster()
1463{
1464 int masterInstance = -1;
1465 for (auto& obj : statusObjects)
1466 {
Chris Cainbd551de2022-04-26 13:41:16 -05001467 auto instance = obj->getOccInstanceID();
Chris Cainbae4d072022-02-28 09:46:50 -06001468#ifdef POWER10
1469 if (!obj->occActive())
1470 {
1471 if (utils::isHostRunning())
1472 {
Chris Cainbd551de2022-04-26 13:41:16 -05001473 // Check if sensor was queued while waiting for discovery
1474 auto match = queuedActiveState.find(instance);
1475 if (match != queuedActiveState.end())
Chris Cainbae4d072022-02-28 09:46:50 -06001476 {
Chris Cain7f89e4d2022-05-09 13:27:45 -05001477 queuedActiveState.erase(match);
Chris Cainbae4d072022-02-28 09:46:50 -06001478 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -06001479 std::format(
Chris Cainbd551de2022-04-26 13:41:16 -05001480 "validateOccMaster: OCC{} is ACTIVE (queued)",
1481 instance)
Chris Cainbae4d072022-02-28 09:46:50 -06001482 .c_str());
Chris Cainbd551de2022-04-26 13:41:16 -05001483 obj->occActive(true);
1484 }
1485 else
1486 {
1487 // OCC does not appear to be active yet, check active sensor
Patrick Williamsfb0a5c32024-02-28 11:27:00 -06001488#ifdef PLDM
Chris Cainbd551de2022-04-26 13:41:16 -05001489 pldmHandle->checkActiveSensor(instance);
Patrick Williamsfb0a5c32024-02-28 11:27:00 -06001490#endif
Chris Cainbd551de2022-04-26 13:41:16 -05001491 if (obj->occActive())
1492 {
1493 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -06001494 std::format(
Chris Cainbd551de2022-04-26 13:41:16 -05001495 "validateOccMaster: OCC{} is ACTIVE after reading sensor",
1496 instance)
1497 .c_str());
1498 }
Chris Cainbae4d072022-02-28 09:46:50 -06001499 }
1500 }
1501 else
1502 {
1503 log<level::WARNING>(
Patrick Williams48002492024-02-13 21:43:32 -06001504 std::format(
Chris Cainbae4d072022-02-28 09:46:50 -06001505 "validateOccMaster: HOST is not running (OCC{})",
Chris Cainbd551de2022-04-26 13:41:16 -05001506 instance)
Chris Cainbae4d072022-02-28 09:46:50 -06001507 .c_str());
1508 return;
1509 }
1510 }
1511#endif // POWER10
1512
Chris Caina7b74dc2021-11-10 17:03:43 -06001513 if (obj->isMasterOcc())
1514 {
Chris Cain5d66a0a2022-02-09 08:52:10 -06001515 obj->addPresenceWatchMaster();
1516
Chris Caina7b74dc2021-11-10 17:03:43 -06001517 if (masterInstance == -1)
1518 {
Chris Cainbd551de2022-04-26 13:41:16 -05001519 masterInstance = instance;
Chris Caina7b74dc2021-11-10 17:03:43 -06001520 }
1521 else
1522 {
1523 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -06001524 std::format(
Chris Caina7b74dc2021-11-10 17:03:43 -06001525 "validateOccMaster: Multiple OCC masters! ({} and {})",
Chris Cainbd551de2022-04-26 13:41:16 -05001526 masterInstance, instance)
Chris Caina7b74dc2021-11-10 17:03:43 -06001527 .c_str());
1528 // request reset
Eddie James9789e712022-05-25 15:43:40 -05001529 obj->deviceError(Error::Descriptor(PRESENCE_ERROR_PATH));
Chris Caina7b74dc2021-11-10 17:03:43 -06001530 }
1531 }
1532 }
Chris Cainbae4d072022-02-28 09:46:50 -06001533
Chris Caina7b74dc2021-11-10 17:03:43 -06001534 if (masterInstance < 0)
1535 {
Chris Cainbae4d072022-02-28 09:46:50 -06001536 log<level::ERR>(
Patrick Williams48002492024-02-13 21:43:32 -06001537 std::format("validateOccMaster: Master OCC not found! (of {} OCCs)",
Chris Cainbae4d072022-02-28 09:46:50 -06001538 statusObjects.size())
1539 .c_str());
Chris Caina7b74dc2021-11-10 17:03:43 -06001540 // request reset
Eddie James9789e712022-05-25 15:43:40 -05001541 statusObjects.front()->deviceError(
1542 Error::Descriptor(PRESENCE_ERROR_PATH));
Chris Caina7b74dc2021-11-10 17:03:43 -06001543 }
1544 else
1545 {
1546 log<level::INFO>(
Patrick Williams48002492024-02-13 21:43:32 -06001547 std::format("validateOccMaster: OCC{} is master of {} OCCs",
Chris Cain36f9cde2021-11-22 11:18:21 -06001548 masterInstance, activeCount)
Chris Caina7b74dc2021-11-10 17:03:43 -06001549 .c_str());
Sheldon Bailey31a2f132022-05-20 11:31:52 -05001550#ifdef POWER10
1551 pmode->updateDbusSafeMode(false);
1552#endif
Chris Caina7b74dc2021-11-10 17:03:43 -06001553 }
1554}
1555
Chris Cain40501a22022-03-14 17:33:27 -05001556void Manager::updatePcapBounds() const
1557{
1558 if (pcap)
1559 {
1560 pcap->updatePcapBounds();
1561 }
1562}
1563
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +05301564} // namespace occ
1565} // namespace open_power