1dfc7ec73SVishwanatha Subbanna #include "config.h"
2dfc7ec73SVishwanatha Subbanna 
394df8c90SGunnar Mills #include "occ_manager.hpp"
494df8c90SGunnar Mills 
594df8c90SGunnar Mills #include "i2c_occ.hpp"
6bb895cb8SChicago Duan #include "occ_dbus.hpp"
794df8c90SGunnar Mills #include "utils.hpp"
894df8c90SGunnar Mills 
9bb895cb8SChicago Duan #include <cmath>
1094df8c90SGunnar Mills #include <experimental/filesystem>
1194df8c90SGunnar Mills #include <phosphor-logging/elog-errors.hpp>
1294df8c90SGunnar Mills #include <phosphor-logging/log.hpp>
13bb895cb8SChicago Duan #include <regex>
1494df8c90SGunnar Mills #include <xyz/openbmc_project/Common/error.hpp>
1594df8c90SGunnar Mills 
16dfc7ec73SVishwanatha Subbanna namespace open_power
17dfc7ec73SVishwanatha Subbanna {
18dfc7ec73SVishwanatha Subbanna namespace occ
19dfc7ec73SVishwanatha Subbanna {
20dfc7ec73SVishwanatha Subbanna 
21*8b8abeedSMatt Spinler constexpr uint32_t fruTypeNotAvailable = 0xFF;
22*8b8abeedSMatt Spinler 
23a8857c50SChris Cain using namespace phosphor::logging;
24a8857c50SChris Cain 
25dfc7ec73SVishwanatha Subbanna void Manager::findAndCreateObjects()
26dfc7ec73SVishwanatha Subbanna {
27dfc7ec73SVishwanatha Subbanna     for (auto id = 0; id < MAX_CPUS; ++id)
28dfc7ec73SVishwanatha Subbanna     {
2930417a15SDeepak Kodihalli         // Create one occ per cpu
3030417a15SDeepak Kodihalli         auto occ = std::string(OCC_NAME) + std::to_string(id);
31dfc7ec73SVishwanatha Subbanna         createObjects(occ);
32dfc7ec73SVishwanatha Subbanna     }
33dfc7ec73SVishwanatha Subbanna }
34dfc7ec73SVishwanatha Subbanna 
35dfc7ec73SVishwanatha Subbanna int Manager::cpuCreated(sdbusplus::message::message& msg)
36dfc7ec73SVishwanatha Subbanna {
37dfc7ec73SVishwanatha Subbanna     namespace fs = std::experimental::filesystem;
38dfc7ec73SVishwanatha Subbanna 
39dfc7ec73SVishwanatha Subbanna     sdbusplus::message::object_path o;
40dfc7ec73SVishwanatha Subbanna     msg.read(o);
41dfc7ec73SVishwanatha Subbanna     fs::path cpuPath(std::string(std::move(o)));
42dfc7ec73SVishwanatha Subbanna 
43dfc7ec73SVishwanatha Subbanna     auto name = cpuPath.filename().string();
44dfc7ec73SVishwanatha Subbanna     auto index = name.find(CPU_NAME);
45dfc7ec73SVishwanatha Subbanna     name.replace(index, std::strlen(CPU_NAME), OCC_NAME);
46dfc7ec73SVishwanatha Subbanna 
47dfc7ec73SVishwanatha Subbanna     createObjects(name);
48dfc7ec73SVishwanatha Subbanna 
49dfc7ec73SVishwanatha Subbanna     return 0;
50dfc7ec73SVishwanatha Subbanna }
51dfc7ec73SVishwanatha Subbanna 
52dfc7ec73SVishwanatha Subbanna void Manager::createObjects(const std::string& occ)
53dfc7ec73SVishwanatha Subbanna {
54dfc7ec73SVishwanatha Subbanna     auto path = fs::path(OCC_CONTROL_ROOT) / occ;
55dfc7ec73SVishwanatha Subbanna 
56dfc7ec73SVishwanatha Subbanna     passThroughObjects.emplace_back(
57f3b7514eSGeorge Liu         std::make_unique<PassThrough>(path.c_str()));
58dfc7ec73SVishwanatha Subbanna 
5994df8c90SGunnar Mills     statusObjects.emplace_back(std::make_unique<Status>(
60f3b7514eSGeorge Liu         event, path.c_str(), *this,
6194df8c90SGunnar Mills         std::bind(std::mem_fn(&Manager::statusCallBack), this,
6200325238STom Joseph                   std::placeholders::_1)
6300325238STom Joseph #ifdef PLDM
6400325238STom Joseph             ,
6500325238STom Joseph         std::bind(std::mem_fn(&pldm::Interface::resetOCC), pldmHandle.get(),
6600325238STom Joseph                   std::placeholders::_1)
6700325238STom Joseph #endif
6800325238STom Joseph             ));
69dfc7ec73SVishwanatha Subbanna 
70dfc7ec73SVishwanatha Subbanna     // Create the power cap monitor object for master occ (0)
71dfc7ec73SVishwanatha Subbanna     if (!pcap)
72dfc7ec73SVishwanatha Subbanna     {
73dfc7ec73SVishwanatha Subbanna         pcap = std::make_unique<open_power::occ::powercap::PowerCap>(
74f3b7514eSGeorge Liu             *statusObjects.front());
75dfc7ec73SVishwanatha Subbanna     }
7678e86012SChris Cain 
7778e86012SChris Cain #ifdef POWER10
7878e86012SChris Cain     // Create the power mode monitor object for master occ (0)
7978e86012SChris Cain     if (!pmode)
8078e86012SChris Cain     {
8178e86012SChris Cain         pmode = std::make_unique<open_power::occ::powermode::PowerMode>(
8278e86012SChris Cain             *statusObjects.front());
8378e86012SChris Cain     }
8478e86012SChris Cain #endif
85dfc7ec73SVishwanatha Subbanna }
86dfc7ec73SVishwanatha Subbanna 
87dfc7ec73SVishwanatha Subbanna void Manager::statusCallBack(bool status)
88dfc7ec73SVishwanatha Subbanna {
8994df8c90SGunnar Mills     using InternalFailure =
9094df8c90SGunnar Mills         sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
91dfc7ec73SVishwanatha Subbanna 
92dfc7ec73SVishwanatha Subbanna     // At this time, it won't happen but keeping it
93dfc7ec73SVishwanatha Subbanna     // here just in case something changes in the future
94dfc7ec73SVishwanatha Subbanna     if ((activeCount == 0) && (!status))
95dfc7ec73SVishwanatha Subbanna     {
96dfc7ec73SVishwanatha Subbanna         log<level::ERR>("Invalid update on OCCActive");
97dfc7ec73SVishwanatha Subbanna         elog<InternalFailure>();
98dfc7ec73SVishwanatha Subbanna     }
99dfc7ec73SVishwanatha Subbanna 
100dfc7ec73SVishwanatha Subbanna     activeCount += status ? 1 : -1;
101dae2d940SEddie James 
102dae2d940SEddie James     // Only start presence detection if all the OCCs are bound
103dae2d940SEddie James     if (activeCount == statusObjects.size())
104dae2d940SEddie James     {
105dae2d940SEddie James         for (auto& obj : statusObjects)
106dae2d940SEddie James         {
107dae2d940SEddie James             obj->addPresenceWatchMaster();
108dae2d940SEddie James         }
109dae2d940SEddie James     }
110a8857c50SChris Cain 
111a8857c50SChris Cain     if ((!_pollTimer->isEnabled()) && (activeCount > 0))
112a8857c50SChris Cain     {
113a8857c50SChris Cain         log<level::INFO>(fmt::format("Manager::statusCallBack(): {} OCCs will "
114a8857c50SChris Cain                                      "be polled every {} seconds",
115a8857c50SChris Cain                                      activeCount, pollInterval)
116a8857c50SChris Cain                              .c_str());
117a8857c50SChris Cain 
118a8857c50SChris Cain         // Send poll and start OCC poll timer
119a8857c50SChris Cain         pollerTimerExpired();
120a8857c50SChris Cain     }
121a8857c50SChris Cain     else if ((_pollTimer->isEnabled()) && (activeCount == 0))
122a8857c50SChris Cain     {
123a8857c50SChris Cain         // Stop OCC poll timer
124a8857c50SChris Cain         log<level::INFO>("Manager::statusCallBack(): OCCs are not running, "
125a8857c50SChris Cain                          "stopping poll timer");
126a8857c50SChris Cain         _pollTimer->setEnabled(false);
127a8857c50SChris Cain     }
128dfc7ec73SVishwanatha Subbanna }
129dfc7ec73SVishwanatha Subbanna 
130dfc7ec73SVishwanatha Subbanna #ifdef I2C_OCC
131dfc7ec73SVishwanatha Subbanna void Manager::initStatusObjects()
132dfc7ec73SVishwanatha Subbanna {
133dfc7ec73SVishwanatha Subbanna     // Make sure we have a valid path string
134dfc7ec73SVishwanatha Subbanna     static_assert(sizeof(DEV_PATH) != 0);
135dfc7ec73SVishwanatha Subbanna 
136dfc7ec73SVishwanatha Subbanna     auto deviceNames = i2c_occ::getOccHwmonDevices(DEV_PATH);
13741470e56SLei YU     auto occMasterName = deviceNames.front();
138dfc7ec73SVishwanatha Subbanna     for (auto& name : deviceNames)
139dfc7ec73SVishwanatha Subbanna     {
140dfc7ec73SVishwanatha Subbanna         i2c_occ::i2cToDbus(name);
141b5259a1eSLei YU         name = std::string(OCC_NAME) + '_' + name;
142dfc7ec73SVishwanatha Subbanna         auto path = fs::path(OCC_CONTROL_ROOT) / name;
143dfc7ec73SVishwanatha Subbanna         statusObjects.emplace_back(
144f3b7514eSGeorge Liu             std::make_unique<Status>(event, path.c_str(), *this));
145dfc7ec73SVishwanatha Subbanna     }
14641470e56SLei YU     // The first device is master occ
14741470e56SLei YU     pcap = std::make_unique<open_power::occ::powercap::PowerCap>(
148f3b7514eSGeorge Liu         *statusObjects.front(), occMasterName);
14978e86012SChris Cain #ifdef POWER10
15078e86012SChris Cain     pmode = std::make_unique<open_power::occ::powermode::PowerMode>(
15178e86012SChris Cain         *statusObjects.front());
15278e86012SChris Cain #endif
153dfc7ec73SVishwanatha Subbanna }
154dfc7ec73SVishwanatha Subbanna #endif
155dfc7ec73SVishwanatha Subbanna 
156815f9f55STom Joseph #ifdef PLDM
157815f9f55STom Joseph bool Manager::updateOCCActive(instanceID instance, bool status)
158815f9f55STom Joseph {
159815f9f55STom Joseph     return (statusObjects[instance])->occActive(status);
160815f9f55STom Joseph }
161815f9f55STom Joseph #endif
162815f9f55STom Joseph 
163a8857c50SChris Cain void Manager::pollerTimerExpired()
164a8857c50SChris Cain {
165a8857c50SChris Cain     if (activeCount == 0)
166a8857c50SChris Cain     {
167a8857c50SChris Cain         // No OCCs running, so poll timer will not be restarted
168a8857c50SChris Cain         log<level::INFO>("Manager::pollerTimerExpire(): No OCCs running, poll "
169a8857c50SChris Cain                          "timer not restarted");
170a8857c50SChris Cain     }
171a8857c50SChris Cain 
172a8857c50SChris Cain     if (!_pollTimer)
173a8857c50SChris Cain     {
174a8857c50SChris Cain         log<level::ERR>(
175a8857c50SChris Cain             "Manager::pollerTimerExpired() ERROR: Timer not defined");
176a8857c50SChris Cain         return;
177a8857c50SChris Cain     }
178a8857c50SChris Cain 
179a8857c50SChris Cain     for (auto& obj : statusObjects)
180a8857c50SChris Cain     {
181a8857c50SChris Cain         // Read sysfs to force kernel to poll OCC
182a8857c50SChris Cain         obj->readOccState();
183bb895cb8SChicago Duan 
184bb895cb8SChicago Duan #ifdef READ_OCC_SENSORS
185bb895cb8SChicago Duan         // Read occ sensor values
186bb895cb8SChicago Duan         auto id = obj->getOccInstanceID();
187bb895cb8SChicago Duan         if (!obj->occActive())
188bb895cb8SChicago Duan         {
189bb895cb8SChicago Duan             // Occ not activated
190bb895cb8SChicago Duan             setSensorValueToNaN(id);
191bb895cb8SChicago Duan             continue;
192bb895cb8SChicago Duan         }
193bb895cb8SChicago Duan         getSensorValues(id, obj->isMasterOcc());
194bb895cb8SChicago Duan #endif
195a8857c50SChris Cain     }
196a8857c50SChris Cain 
197a8857c50SChris Cain     // Restart OCC poll timer
198a8857c50SChris Cain     _pollTimer->restartOnce(std::chrono::seconds(pollInterval));
199a8857c50SChris Cain }
200a8857c50SChris Cain 
201bb895cb8SChicago Duan #ifdef READ_OCC_SENSORS
202bb895cb8SChicago Duan void Manager::readTempSensors(const fs::path& path, uint32_t id)
203bb895cb8SChicago Duan {
204bb895cb8SChicago Duan     const int open_errno = errno;
205bb895cb8SChicago Duan     std::regex expr{"temp\\d+_label$"}; // Example: temp5_label
206bb895cb8SChicago Duan     for (auto& file : fs::directory_iterator(path))
207bb895cb8SChicago Duan     {
208bb895cb8SChicago Duan         if (!std::regex_search(file.path().string(), expr))
209bb895cb8SChicago Duan         {
210bb895cb8SChicago Duan             continue;
211bb895cb8SChicago Duan         }
212bb895cb8SChicago Duan         std::ifstream fileOpen(file.path(), std::ios::in);
213bb895cb8SChicago Duan         if (!fileOpen)
214bb895cb8SChicago Duan         {
215bb895cb8SChicago Duan             // If not able to read, OCC may be offline
216bb895cb8SChicago Duan             log<level::DEBUG>(
217bb895cb8SChicago Duan                 fmt::format("readTempSensors: open failed(errno = {}) ",
218bb895cb8SChicago Duan                             open_errno)
219bb895cb8SChicago Duan                     .c_str());
220bb895cb8SChicago Duan 
221bb895cb8SChicago Duan             continue;
222bb895cb8SChicago Duan         }
223bb895cb8SChicago Duan         std::string labelValue;
224bb895cb8SChicago Duan         fileOpen >> labelValue;
225bb895cb8SChicago Duan         fileOpen.close();
226bb895cb8SChicago Duan 
227bb895cb8SChicago Duan         const std::string& tempLabel = "label";
228bb895cb8SChicago Duan         const std::string filePathString = file.path().string().substr(
229bb895cb8SChicago Duan             0, file.path().string().length() - tempLabel.length());
230bb895cb8SChicago Duan         std::ifstream fruTypeFile(filePathString + "fru_type", std::ios::in);
231bb895cb8SChicago Duan         if (!fruTypeFile)
232bb895cb8SChicago Duan         {
233bb895cb8SChicago Duan             // If not able to read, OCC may be offline
234bb895cb8SChicago Duan             log<level::DEBUG>(
235bb895cb8SChicago Duan                 fmt::format("readTempSensors: open failed(errno = {}) ",
236bb895cb8SChicago Duan                             open_errno)
237bb895cb8SChicago Duan                     .c_str());
238bb895cb8SChicago Duan             continue;
239bb895cb8SChicago Duan         }
240bb895cb8SChicago Duan         uint32_t fruTypeValue{0};
241bb895cb8SChicago Duan         fruTypeFile >> fruTypeValue;
242bb895cb8SChicago Duan         fruTypeFile.close();
243bb895cb8SChicago Duan 
244bb895cb8SChicago Duan         std::string sensorPath =
245bb895cb8SChicago Duan             OCC_SENSORS_ROOT + std::string("/temperature/");
246bb895cb8SChicago Duan 
247bb895cb8SChicago Duan         if (fruTypeValue == VRMVdd)
248bb895cb8SChicago Duan         {
249bb895cb8SChicago Duan             sensorPath.append("vrm_vdd" + std::to_string(id) + "_temp");
250bb895cb8SChicago Duan         }
251bb895cb8SChicago Duan         else
252bb895cb8SChicago Duan         {
253bb895cb8SChicago Duan             auto sensorTypeID =
254bb895cb8SChicago Duan                 open_power::occ::utils::checkLabelValue(labelValue);
255bb895cb8SChicago Duan             if (sensorTypeID == std::nullopt)
256bb895cb8SChicago Duan             {
257bb895cb8SChicago Duan                 continue;
258bb895cb8SChicago Duan             }
259bb895cb8SChicago Duan             auto& [type, instanceID] = *sensorTypeID;
260bb895cb8SChicago Duan 
261bb895cb8SChicago Duan             if (type == OCC_DIMM_TEMP_SENSOR_TYPE)
262bb895cb8SChicago Duan             {
263*8b8abeedSMatt Spinler                 if (fruTypeValue == fruTypeNotAvailable)
264*8b8abeedSMatt Spinler                 {
265*8b8abeedSMatt Spinler                     // Not all DIMM related temps are available to read
266*8b8abeedSMatt Spinler                     // (no _input file in this case)
267*8b8abeedSMatt Spinler                     continue;
268*8b8abeedSMatt Spinler                 }
269bb895cb8SChicago Duan                 auto iter = dimmTempSensorName.find(fruTypeValue);
270bb895cb8SChicago Duan                 if (iter == dimmTempSensorName.end())
271bb895cb8SChicago Duan                 {
272bb895cb8SChicago Duan                     log<level::ERR>(fmt::format("readTempSensors: Fru type "
273bb895cb8SChicago Duan                                                 "error! fruTypeValue = {}) ",
274bb895cb8SChicago Duan                                                 fruTypeValue)
275bb895cb8SChicago Duan                                         .c_str());
276bb895cb8SChicago Duan                     continue;
277bb895cb8SChicago Duan                 }
278bb895cb8SChicago Duan 
279bb895cb8SChicago Duan                 sensorPath.append("dimm" + std::to_string(instanceID) +
280bb895cb8SChicago Duan                                   iter->second);
281bb895cb8SChicago Duan             }
282bb895cb8SChicago Duan             else if (type == OCC_CPU_TEMP_SENSOR_TYPE)
283bb895cb8SChicago Duan             {
284bb895cb8SChicago Duan                 if (fruTypeValue != processorCore)
285bb895cb8SChicago Duan                 {
286bb895cb8SChicago Duan                     log<level::ERR>(fmt::format("readTempSensors: Fru type "
287bb895cb8SChicago Duan                                                 "error! fruTypeValue = {}) ",
288bb895cb8SChicago Duan                                                 fruTypeValue)
289bb895cb8SChicago Duan                                         .c_str());
290bb895cb8SChicago Duan                     continue;
291bb895cb8SChicago Duan                 }
292bb895cb8SChicago Duan 
293bb895cb8SChicago Duan                 sensorPath.append("proc" + std::to_string(id) + "_core" +
294bb895cb8SChicago Duan                                   std::to_string(instanceID) + "_temp");
295bb895cb8SChicago Duan             }
296bb895cb8SChicago Duan             else
297bb895cb8SChicago Duan             {
298bb895cb8SChicago Duan                 continue;
299bb895cb8SChicago Duan             }
300bb895cb8SChicago Duan         }
301bb895cb8SChicago Duan 
302bb895cb8SChicago Duan         std::ifstream faultPathFile(filePathString + "fault", std::ios::in);
303bb895cb8SChicago Duan         if (faultPathFile)
304bb895cb8SChicago Duan         {
305bb895cb8SChicago Duan             uint32_t faultValue;
306bb895cb8SChicago Duan             faultPathFile >> faultValue;
307bb895cb8SChicago Duan             faultPathFile.close();
308bb895cb8SChicago Duan 
309bb895cb8SChicago Duan             if (faultValue != 0)
310bb895cb8SChicago Duan             {
311bb895cb8SChicago Duan                 open_power::occ::dbus::OccDBusSensors::getOccDBus().setValue(
312bb895cb8SChicago Duan                     sensorPath, std::numeric_limits<double>::quiet_NaN());
313bb895cb8SChicago Duan 
314bb895cb8SChicago Duan                 open_power::occ::dbus::OccDBusSensors::getOccDBus()
315bb895cb8SChicago Duan                     .setOperationalStatus(sensorPath, false);
316bb895cb8SChicago Duan 
317bb895cb8SChicago Duan                 continue;
318bb895cb8SChicago Duan             }
319bb895cb8SChicago Duan         }
320bb895cb8SChicago Duan 
321bb895cb8SChicago Duan         std::ifstream inputFile(filePathString + "input", std::ios::in);
322bb895cb8SChicago Duan         if (inputFile)
323bb895cb8SChicago Duan         {
324bb895cb8SChicago Duan             double tempValue;
325bb895cb8SChicago Duan             inputFile >> tempValue;
326bb895cb8SChicago Duan 
327bb895cb8SChicago Duan             inputFile.close();
328bb895cb8SChicago Duan 
329bb895cb8SChicago Duan             open_power::occ::dbus::OccDBusSensors::getOccDBus().setValue(
330bb895cb8SChicago Duan                 sensorPath, tempValue * std::pow(10, -3));
331bb895cb8SChicago Duan 
332bb895cb8SChicago Duan             open_power::occ::dbus::OccDBusSensors::getOccDBus()
333bb895cb8SChicago Duan                 .setOperationalStatus(sensorPath, true);
334bb895cb8SChicago Duan 
335bb895cb8SChicago Duan             existingSensors[sensorPath] = id;
336bb895cb8SChicago Duan         }
337bb895cb8SChicago Duan         else
338bb895cb8SChicago Duan         {
339bb895cb8SChicago Duan             // If not able to read, OCC may be offline
340bb895cb8SChicago Duan             log<level::DEBUG>(
341bb895cb8SChicago Duan                 fmt::format("readTempSensors: open failed(errno = {}) ",
342bb895cb8SChicago Duan                             open_errno)
343bb895cb8SChicago Duan                     .c_str());
344bb895cb8SChicago Duan         }
345bb895cb8SChicago Duan     }
346bb895cb8SChicago Duan     return;
347bb895cb8SChicago Duan }
348bb895cb8SChicago Duan 
349bb895cb8SChicago Duan std::optional<std::string>
350bb895cb8SChicago Duan     Manager::getPowerLabelFunctionID(const std::string& value)
351bb895cb8SChicago Duan {
352bb895cb8SChicago Duan     // If the value is "system", then the FunctionID is "system".
353bb895cb8SChicago Duan     if (value == "system")
354bb895cb8SChicago Duan     {
355bb895cb8SChicago Duan         return value;
356bb895cb8SChicago Duan     }
357bb895cb8SChicago Duan 
358bb895cb8SChicago Duan     // If the value is not "system", then the label value have 3 numbers, of
359bb895cb8SChicago Duan     // which we only care about the middle one:
360bb895cb8SChicago Duan     // <sensor id>_<function id>_<apss channel>
361bb895cb8SChicago Duan     // eg: The value is "0_10_5" , then the FunctionID is "10".
362bb895cb8SChicago Duan     if (value.find("_") == std::string::npos)
363bb895cb8SChicago Duan     {
364bb895cb8SChicago Duan         return std::nullopt;
365bb895cb8SChicago Duan     }
366bb895cb8SChicago Duan 
367bb895cb8SChicago Duan     auto powerLabelValue = value.substr((value.find("_") + 1));
368bb895cb8SChicago Duan 
369bb895cb8SChicago Duan     if (powerLabelValue.find("_") == std::string::npos)
370bb895cb8SChicago Duan     {
371bb895cb8SChicago Duan         return std::nullopt;
372bb895cb8SChicago Duan     }
373bb895cb8SChicago Duan 
374bb895cb8SChicago Duan     return powerLabelValue.substr(0, powerLabelValue.find("_"));
375bb895cb8SChicago Duan }
376bb895cb8SChicago Duan 
377bb895cb8SChicago Duan void Manager::readPowerSensors(const fs::path& path, uint32_t id)
378bb895cb8SChicago Duan {
379bb895cb8SChicago Duan     const int open_errno = errno;
380bb895cb8SChicago Duan     std::regex expr{"power\\d+_label$"}; // Example: power5_label
381bb895cb8SChicago Duan     for (auto& file : fs::directory_iterator(path))
382bb895cb8SChicago Duan     {
383bb895cb8SChicago Duan         if (!std::regex_search(file.path().string(), expr))
384bb895cb8SChicago Duan         {
385bb895cb8SChicago Duan             continue;
386bb895cb8SChicago Duan         }
387bb895cb8SChicago Duan         std::ifstream fileOpen(file.path(), std::ios::in);
388bb895cb8SChicago Duan         if (!fileOpen)
389bb895cb8SChicago Duan         {
390bb895cb8SChicago Duan             // If not able to read, OCC may be offline
391bb895cb8SChicago Duan             log<level::DEBUG>(
392bb895cb8SChicago Duan                 fmt::format("readPowerSensors: open failed(errno = {}) ",
393bb895cb8SChicago Duan                             open_errno)
394bb895cb8SChicago Duan                     .c_str());
395bb895cb8SChicago Duan 
396bb895cb8SChicago Duan             continue;
397bb895cb8SChicago Duan         }
398bb895cb8SChicago Duan         std::string labelValue;
399bb895cb8SChicago Duan         fileOpen >> labelValue;
400bb895cb8SChicago Duan         fileOpen.close();
401bb895cb8SChicago Duan 
402bb895cb8SChicago Duan         auto functionID = getPowerLabelFunctionID(labelValue);
403bb895cb8SChicago Duan         if (functionID == std::nullopt)
404bb895cb8SChicago Duan         {
405bb895cb8SChicago Duan             continue;
406bb895cb8SChicago Duan         }
407bb895cb8SChicago Duan 
408bb895cb8SChicago Duan         const std::string& tempLabel = "label";
409bb895cb8SChicago Duan         const std::string filePathString = file.path().string().substr(
410bb895cb8SChicago Duan             0, file.path().string().length() - tempLabel.length());
411bb895cb8SChicago Duan 
412bb895cb8SChicago Duan         std::string sensorPath = OCC_SENSORS_ROOT + std::string("/power/");
413bb895cb8SChicago Duan 
414bb895cb8SChicago Duan         auto iter = powerSensorName.find(*functionID);
415bb895cb8SChicago Duan         if (iter == powerSensorName.end())
416bb895cb8SChicago Duan         {
417bb895cb8SChicago Duan             continue;
418bb895cb8SChicago Duan         }
419bb895cb8SChicago Duan         sensorPath.append(iter->second);
420bb895cb8SChicago Duan 
421bb895cb8SChicago Duan         std::ifstream faultPathFile(filePathString + "fault", std::ios::in);
422bb895cb8SChicago Duan         if (faultPathFile)
423bb895cb8SChicago Duan         {
424bb895cb8SChicago Duan             uint32_t faultValue{0};
425bb895cb8SChicago Duan             faultPathFile >> faultValue;
426bb895cb8SChicago Duan             faultPathFile.close();
427bb895cb8SChicago Duan 
428bb895cb8SChicago Duan             if (faultValue != 0)
429bb895cb8SChicago Duan             {
430bb895cb8SChicago Duan                 open_power::occ::dbus::OccDBusSensors::getOccDBus().setValue(
431bb895cb8SChicago Duan                     sensorPath, std::numeric_limits<double>::quiet_NaN());
432bb895cb8SChicago Duan 
433bb895cb8SChicago Duan                 open_power::occ::dbus::OccDBusSensors::getOccDBus()
434bb895cb8SChicago Duan                     .setOperationalStatus(sensorPath, false);
435bb895cb8SChicago Duan 
436bb895cb8SChicago Duan                 continue;
437bb895cb8SChicago Duan             }
438bb895cb8SChicago Duan         }
439bb895cb8SChicago Duan 
440bb895cb8SChicago Duan         std::ifstream inputFile(filePathString + "input", std::ios::in);
441bb895cb8SChicago Duan         if (inputFile)
442bb895cb8SChicago Duan         {
443bb895cb8SChicago Duan             double tempValue;
444bb895cb8SChicago Duan             inputFile >> tempValue;
445bb895cb8SChicago Duan             inputFile.close();
446bb895cb8SChicago Duan 
447bb895cb8SChicago Duan             open_power::occ::dbus::OccDBusSensors::getOccDBus().setValue(
448bb895cb8SChicago Duan                 sensorPath, tempValue * std::pow(10, -3) * std::pow(10, -3));
449bb895cb8SChicago Duan 
450bb895cb8SChicago Duan             open_power::occ::dbus::OccDBusSensors::getOccDBus()
451bb895cb8SChicago Duan                 .setOperationalStatus(sensorPath, true);
452bb895cb8SChicago Duan 
453bb895cb8SChicago Duan             existingSensors[sensorPath] = id;
454bb895cb8SChicago Duan         }
455bb895cb8SChicago Duan         else
456bb895cb8SChicago Duan         {
457bb895cb8SChicago Duan             // If not able to read, OCC may be offline
458bb895cb8SChicago Duan             log<level::DEBUG>(
459bb895cb8SChicago Duan                 fmt::format("readPowerSensors: open failed(errno = {}) ",
460bb895cb8SChicago Duan                             open_errno)
461bb895cb8SChicago Duan                     .c_str());
462bb895cb8SChicago Duan         }
463bb895cb8SChicago Duan     }
464bb895cb8SChicago Duan     return;
465bb895cb8SChicago Duan }
466bb895cb8SChicago Duan 
467bb895cb8SChicago Duan void Manager::setSensorValueToNaN(uint32_t id)
468bb895cb8SChicago Duan {
469bb895cb8SChicago Duan     for (const auto& [sensorPath, occId] : existingSensors)
470bb895cb8SChicago Duan     {
471bb895cb8SChicago Duan         if (occId == id)
472bb895cb8SChicago Duan         {
473bb895cb8SChicago Duan             open_power::occ::dbus::OccDBusSensors::getOccDBus().setValue(
474bb895cb8SChicago Duan                 sensorPath, std::numeric_limits<double>::quiet_NaN());
475bb895cb8SChicago Duan         }
476bb895cb8SChicago Duan     }
477bb895cb8SChicago Duan     return;
478bb895cb8SChicago Duan }
479bb895cb8SChicago Duan 
480bb895cb8SChicago Duan void Manager::getSensorValues(uint32_t id, bool masterOcc)
481bb895cb8SChicago Duan {
482bb895cb8SChicago Duan     const auto occ = std::string("occ-hwmon.") + std::to_string(id + 1);
483bb895cb8SChicago Duan 
484bb895cb8SChicago Duan     fs::path fileName{OCC_HWMON_PATH + occ + "/hwmon/"};
485bb895cb8SChicago Duan 
486bb895cb8SChicago Duan     // Need to get the hwmonXX directory name, there better only be 1 dir
487bb895cb8SChicago Duan     assert(std::distance(fs::directory_iterator(fileName),
488bb895cb8SChicago Duan                          fs::directory_iterator{}) == 1);
489bb895cb8SChicago Duan     // Now set our path to this full path, including this hwmonXX directory
490bb895cb8SChicago Duan     fileName = fs::path(*fs::directory_iterator(fileName));
491bb895cb8SChicago Duan 
492bb895cb8SChicago Duan     // Read temperature sensors
493bb895cb8SChicago Duan     readTempSensors(fileName, id);
494bb895cb8SChicago Duan 
495bb895cb8SChicago Duan     if (masterOcc)
496bb895cb8SChicago Duan     {
497bb895cb8SChicago Duan         // Read power sensors
498bb895cb8SChicago Duan         readPowerSensors(fileName, id);
499bb895cb8SChicago Duan     }
500bb895cb8SChicago Duan 
501bb895cb8SChicago Duan     return;
502bb895cb8SChicago Duan }
503bb895cb8SChicago Duan #endif
504bb895cb8SChicago Duan 
505dfc7ec73SVishwanatha Subbanna } // namespace occ
506dfc7ec73SVishwanatha Subbanna } // namespace open_power
507