blob: 3801d40244b81575534e93550e239bceff4000b8 [file] [log] [blame]
Matt Spinlerb54357f2017-08-21 14:38:54 -05001/**
2 * Copyright © 2017 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Matt Spinlerf0f02b92018-10-25 16:12:43 -050016#include "ucd90160.hpp"
17
18#include "names_values.hpp"
19#include "utility.hpp"
20
21#include <elog-errors.hpp>
Matt Spinlerf0f02b92018-10-25 16:12:43 -050022#include <org/open_power/Witherspoon/Fault/error.hpp>
Matt Spinlerb54357f2017-08-21 14:38:54 -050023#include <phosphor-logging/elog.hpp>
24#include <phosphor-logging/log.hpp>
Matt Spinlerceacf942017-10-05 13:55:02 -050025#include <xyz/openbmc_project/Common/Device/error.hpp>
Matt Spinlerb54357f2017-08-21 14:38:54 -050026
Brandon Wymand1bc4ce2019-12-13 14:20:34 -060027#include <map>
28#include <memory>
29
Lei YUab093322019-10-09 16:43:22 +080030namespace phosphor
Matt Spinlerb54357f2017-08-21 14:38:54 -050031{
32namespace power
33{
34
35using namespace std::string_literals;
36
Matt Spinlere7e432b2017-08-21 15:01:40 -050037const auto MFR_STATUS = "mfr_status"s;
Matt Spinler1e365692017-08-21 14:43:55 -050038
Matt Spinlerb54357f2017-08-21 14:38:54 -050039const auto DEVICE_NAME = "UCD90160"s;
40const auto DRIVER_NAME = "ucd9000"s;
Matt Spinlere7e432b2017-08-21 15:01:40 -050041constexpr auto NUM_PAGES = 16;
Matt Spinlerb54357f2017-08-21 14:38:54 -050042
Matt Spinler0e45ced2018-02-12 14:36:07 -060043constexpr auto INVENTORY_OBJ_PATH = "/xyz/openbmc_project/inventory";
44
Brandon Wyman9c7897c2019-03-28 17:42:34 -050045namespace fs = std::filesystem;
Matt Spinlerd998b732017-08-21 15:35:54 -050046using namespace gpio;
Matt Spinlerb54357f2017-08-21 14:38:54 -050047using namespace pmbus;
48using namespace phosphor::logging;
Matt Spinlerceacf942017-10-05 13:55:02 -050049
Matt Spinlerf0f02b92018-10-25 16:12:43 -050050namespace device_error = sdbusplus::xyz::openbmc_project::Common::Device::Error;
51namespace power_error = sdbusplus::org::open_power::Witherspoon::Fault::Error;
Matt Spinlerb54357f2017-08-21 14:38:54 -050052
Patrick Williams7354ce62022-07-22 19:26:56 -050053UCD90160::UCD90160(size_t instance, sdbusplus::bus_t& bus) :
Matt Spinlerf0f02b92018-10-25 16:12:43 -050054 Device(DEVICE_NAME, instance),
55 interface(std::get<ucd90160::pathField>(deviceMap.find(instance)->second),
56 DRIVER_NAME, instance),
57 gpioDevice(findGPIODevice(interface.path())), bus(bus)
Adriana Kobylak0c9a33d2021-09-13 18:05:09 +000058{}
Matt Spinlerb54357f2017-08-21 14:38:54 -050059
60void UCD90160::onFailure()
61{
62 try
63 {
64 auto voutError = checkVOUTFaults();
65
66 auto pgoodError = checkPGOODFaults(false);
67
Matt Spinlerf0f02b92018-10-25 16:12:43 -050068 // Not a voltage or PGOOD fault, but we know something
69 // failed so still create an error log.
Matt Spinlerb54357f2017-08-21 14:38:54 -050070 if (!voutError && !pgoodError)
71 {
72 createPowerFaultLog();
73 }
74 }
Patrick Williamsc1d4de52021-10-06 12:45:57 -050075 catch (const device_error::ReadFailure& e)
Matt Spinlerb54357f2017-08-21 14:38:54 -050076 {
77 if (!accessError)
78 {
Matt Spinlerceacf942017-10-05 13:55:02 -050079 commit<device_error::ReadFailure>();
Matt Spinlerb54357f2017-08-21 14:38:54 -050080 accessError = true;
81 }
82 }
83}
84
85void UCD90160::analyze()
86{
87 try
88 {
Matt Spinlerf0f02b92018-10-25 16:12:43 -050089 // Note: Voltage faults are always fatal, so they just
90 // need to be analyzed in onFailure().
Matt Spinlerb54357f2017-08-21 14:38:54 -050091
92 checkPGOODFaults(true);
93 }
Patrick Williamsc1d4de52021-10-06 12:45:57 -050094 catch (const device_error::ReadFailure& e)
Matt Spinlerb54357f2017-08-21 14:38:54 -050095 {
96 if (!accessError)
97 {
Matt Spinlerceacf942017-10-05 13:55:02 -050098 commit<device_error::ReadFailure>();
Matt Spinlerb54357f2017-08-21 14:38:54 -050099 accessError = true;
100 }
101 }
102}
103
Matt Spinlere7e432b2017-08-21 15:01:40 -0500104uint16_t UCD90160::readStatusWord()
105{
106 return interface.read(STATUS_WORD, Type::Debug);
107}
108
109uint32_t UCD90160::readMFRStatus()
110{
Matt Spinler233a2522018-03-30 14:40:04 -0500111 return interface.read(MFR_STATUS, Type::HwmonDeviceDebug);
Matt Spinlere7e432b2017-08-21 15:01:40 -0500112}
113
Matt Spinlerb54357f2017-08-21 14:38:54 -0500114bool UCD90160::checkVOUTFaults()
115{
Matt Spinlere7e432b2017-08-21 15:01:40 -0500116 bool errorCreated = false;
117 auto statusWord = readStatusWord();
118
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500119 // The status_word register has a summary bit to tell us
120 // if each page even needs to be checked
Matt Spinlere7e432b2017-08-21 15:01:40 -0500121 if (!(statusWord & status_word::VOUT_FAULT))
122 {
123 return errorCreated;
124 }
125
126 for (size_t page = 0; page < NUM_PAGES; page++)
127 {
128 if (isVoutFaultLogged(page))
129 {
130 continue;
131 }
132
133 auto statusVout = interface.insertPageNum(STATUS_VOUT, page);
134 uint8_t vout = interface.read(statusVout, Type::Debug);
135
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500136 // If any bits are on log them, though some are just
137 // warnings so they won't cause errors
Matt Spinlere7e432b2017-08-21 15:01:40 -0500138 if (vout)
139 {
Matt Spinlerde16d052017-12-13 13:22:14 -0600140 log<level::INFO>("A voltage rail has bits on in STATUS_VOUT",
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500141 entry("STATUS_VOUT=0x%X", vout),
142 entry("PAGE=%d", page));
Matt Spinlerde16d052017-12-13 13:22:14 -0600143 }
144
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500145 // Log errors if any non-warning bits on
Matt Spinlerde16d052017-12-13 13:22:14 -0600146 if (vout & ~status_vout::WARNING_MASK)
147 {
Matt Spinlere7e432b2017-08-21 15:01:40 -0500148 auto& railNames = std::get<ucd90160::railNamesField>(
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500149 deviceMap.find(getInstance())->second);
Matt Spinlere7e432b2017-08-21 15:01:40 -0500150 auto railName = railNames.at(page);
151
152 util::NamesValues nv;
Matt Spinler6def9092018-02-27 14:22:59 -0600153 try
154 {
155 nv.add("STATUS_WORD", statusWord);
156 nv.add("STATUS_VOUT", vout);
157 nv.add("MFR_STATUS", readMFRStatus());
158 }
Patrick Williamsc1d4de52021-10-06 12:45:57 -0500159 catch (const device_error::ReadFailure& e)
Matt Spinler6def9092018-02-27 14:22:59 -0600160 {
161 log<level::ERR>("ReadFailure when collecting metadata");
162 commit<device_error::ReadFailure>();
163 }
Matt Spinlere7e432b2017-08-21 15:01:40 -0500164
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500165 using metadata =
166 org::open_power::Witherspoon::Fault::PowerSequencerVoltageFault;
Matt Spinlere7e432b2017-08-21 15:01:40 -0500167
Matt Spinlerceacf942017-10-05 13:55:02 -0500168 report<power_error::PowerSequencerVoltageFault>(
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500169 metadata::RAIL(page), metadata::RAIL_NAME(railName.c_str()),
170 metadata::RAW_STATUS(nv.get().c_str()));
Matt Spinlere7e432b2017-08-21 15:01:40 -0500171
172 setVoutFaultLogged(page);
173 errorCreated = true;
174 }
175 }
176
177 return errorCreated;
Matt Spinlerb54357f2017-08-21 14:38:54 -0500178}
179
180bool UCD90160::checkPGOODFaults(bool polling)
181{
Matt Spinlerd998b732017-08-21 15:35:54 -0500182 bool errorCreated = false;
183
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500184 // While PGOOD faults could show up in MFR_STATUS (and we could then
185 // check the summary bit in STATUS_WORD first), they are edge triggered,
186 // and as the device driver sends a clear faults command every time we
187 // do a read, we will never see them. So, we'll have to just read the
188 // real time GPI status GPIO.
Matt Spinlerd998b732017-08-21 15:35:54 -0500189
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500190 // Check only the GPIs configured on this system.
Matt Spinlerd998b732017-08-21 15:35:54 -0500191 auto& gpiConfigs = std::get<ucd90160::gpiConfigField>(
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500192 deviceMap.find(getInstance())->second);
Matt Spinlerd998b732017-08-21 15:35:54 -0500193
194 for (const auto& gpiConfig : gpiConfigs)
195 {
196 auto gpiNum = std::get<ucd90160::gpiNumField>(gpiConfig);
197 auto doPoll = std::get<ucd90160::pollField>(gpiConfig);
198
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500199 // Can skip this one if there is already an error on this input,
200 // or we are polling and these inputs don't need to be polled
Matt Spinlerd998b732017-08-21 15:35:54 -0500201 //(because errors on them are fatal).
202 if (isPGOODFaultLogged(gpiNum) || (polling && !doPoll))
203 {
204 continue;
205 }
206
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500207 // The real time status is read via the pin ID
Matt Spinlerd998b732017-08-21 15:35:54 -0500208 auto pinID = std::get<ucd90160::pinIDField>(gpiConfig);
209 auto gpio = gpios.find(pinID);
210 Value gpiStatus;
211
212 try
213 {
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500214 // The first time through, create the GPIO objects
Matt Spinlerd998b732017-08-21 15:35:54 -0500215 if (gpio == gpios.end())
216 {
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500217 gpios.emplace(pinID, std::make_unique<GPIO>(gpioDevice, pinID,
218 Direction::input));
Matt Spinlerd998b732017-08-21 15:35:54 -0500219 gpio = gpios.find(pinID);
220 }
221
222 gpiStatus = gpio->second->read();
223 }
Patrick Williamsc1d4de52021-10-06 12:45:57 -0500224 catch (const std::exception& e)
Matt Spinlerd998b732017-08-21 15:35:54 -0500225 {
226 if (!accessError)
227 {
228 log<level::ERR>(e.what());
229 accessError = true;
230 }
231 continue;
232 }
233
234 if (gpiStatus == Value::low)
235 {
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500236 // There may be some extra analysis we can do to narrow the
237 // error down further. Note that finding an error here won't
238 // prevent us from checking this GPI again.
Matt Spinler8bc12832017-09-19 11:17:54 -0500239 errorCreated = doExtraAnalysis(gpiConfig);
240
241 if (errorCreated)
242 {
243 continue;
244 }
245
Matt Spinlerd998b732017-08-21 15:35:54 -0500246 auto& gpiName = std::get<ucd90160::gpiNameField>(gpiConfig);
247 auto status = (gpiStatus == Value::low) ? 0 : 1;
248
249 util::NamesValues nv;
Matt Spinler6def9092018-02-27 14:22:59 -0600250
251 try
252 {
253 nv.add("STATUS_WORD", readStatusWord());
254 nv.add("MFR_STATUS", readMFRStatus());
255 nv.add("INPUT_STATUS", status);
256 }
Patrick Williamsc1d4de52021-10-06 12:45:57 -0500257 catch (const device_error::ReadFailure& e)
Matt Spinler6def9092018-02-27 14:22:59 -0600258 {
259 log<level::ERR>("ReadFailure when collecting metadata");
260 commit<device_error::ReadFailure>();
261 }
Matt Spinlerd998b732017-08-21 15:35:54 -0500262
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500263 using metadata =
264 org::open_power::Witherspoon::Fault::PowerSequencerPGOODFault;
Matt Spinlerd998b732017-08-21 15:35:54 -0500265
Matt Spinlerceacf942017-10-05 13:55:02 -0500266 report<power_error::PowerSequencerPGOODFault>(
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500267 metadata::INPUT_NUM(gpiNum),
268 metadata::INPUT_NAME(gpiName.c_str()),
269 metadata::RAW_STATUS(nv.get().c_str()));
Matt Spinlerd998b732017-08-21 15:35:54 -0500270
271 setPGOODFaultLogged(gpiNum);
272 errorCreated = true;
273 }
274 }
275
276 return errorCreated;
Matt Spinlerb54357f2017-08-21 14:38:54 -0500277}
278
279void UCD90160::createPowerFaultLog()
280{
Matt Spinler9efb3082017-08-21 15:43:43 -0500281 util::NamesValues nv;
Matt Spinler6def9092018-02-27 14:22:59 -0600282
283 try
284 {
285 nv.add("STATUS_WORD", readStatusWord());
286 nv.add("MFR_STATUS", readMFRStatus());
287 }
Patrick Williamsc1d4de52021-10-06 12:45:57 -0500288 catch (const device_error::ReadFailure& e)
Matt Spinler6def9092018-02-27 14:22:59 -0600289 {
290 log<level::ERR>("ReadFailure when collecting metadata");
291 commit<device_error::ReadFailure>();
292 }
Matt Spinlerb54357f2017-08-21 14:38:54 -0500293
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500294 using metadata = org::open_power::Witherspoon::Fault::PowerSequencerFault;
Matt Spinler9efb3082017-08-21 15:43:43 -0500295
Matt Spinlerceacf942017-10-05 13:55:02 -0500296 report<power_error::PowerSequencerFault>(
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500297 metadata::RAW_STATUS(nv.get().c_str()));
Matt Spinlerb54357f2017-08-21 14:38:54 -0500298}
299
Matt Spinlerfcd4a712017-09-19 10:45:07 -0500300fs::path UCD90160::findGPIODevice(const fs::path& path)
Matt Spinler110b2842017-08-21 15:23:27 -0500301{
Matt Spinlerfcd4a712017-09-19 10:45:07 -0500302 fs::path gpioDevicePath;
Matt Spinler110b2842017-08-21 15:23:27 -0500303
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500304 // In the driver directory, look for a subdirectory
305 // named gpiochipX, where X is some number. Then
306 // we'll access the GPIO at /dev/gpiochipX.
Matt Spinler110b2842017-08-21 15:23:27 -0500307 if (fs::is_directory(path))
308 {
309 for (auto& f : fs::directory_iterator(path))
310 {
311 if (f.path().filename().string().find("gpiochip") !=
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500312 std::string::npos)
Matt Spinler110b2842017-08-21 15:23:27 -0500313 {
Matt Spinlerfcd4a712017-09-19 10:45:07 -0500314 gpioDevicePath = "/dev" / f.path().filename();
Matt Spinler110b2842017-08-21 15:23:27 -0500315 break;
316 }
317 }
318 }
319
Matt Spinlerfcd4a712017-09-19 10:45:07 -0500320 if (gpioDevicePath.empty())
Matt Spinler110b2842017-08-21 15:23:27 -0500321 {
Matt Spinlerfcd4a712017-09-19 10:45:07 -0500322 log<level::ERR>("Could not find GPIO device path",
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500323 entry("BASE_PATH=%s", path.c_str()));
Matt Spinler110b2842017-08-21 15:23:27 -0500324 }
Matt Spinlerfcd4a712017-09-19 10:45:07 -0500325
326 return gpioDevicePath;
Matt Spinler110b2842017-08-21 15:23:27 -0500327}
328
Matt Spinler8bc12832017-09-19 11:17:54 -0500329bool UCD90160::doExtraAnalysis(const ucd90160::GPIConfig& config)
330{
331
332 auto type = std::get<ucd90160::extraAnalysisField>(config);
333 if (type == ucd90160::extraAnalysisType::none)
334 {
335 return false;
336 }
337
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500338 // Currently the only extra analysis to do is to check other GPIOs.
Matt Spinler8bc12832017-09-19 11:17:54 -0500339 return doGPIOAnalysis(type);
340}
341
342bool UCD90160::doGPIOAnalysis(ucd90160::extraAnalysisType type)
343{
344 bool errorFound = false;
Matt Spinlera8269652017-09-19 15:13:28 -0500345 bool shutdown = false;
Matt Spinler8bc12832017-09-19 11:17:54 -0500346
347 const auto& analysisConfig = std::get<ucd90160::gpioAnalysisField>(
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500348 deviceMap.find(getInstance())->second);
Matt Spinler8bc12832017-09-19 11:17:54 -0500349
350 auto gpioConfig = analysisConfig.find(type);
351 if (gpioConfig == analysisConfig.end())
352 {
353 return errorFound;
354 }
355
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500356 auto path = std::get<ucd90160::gpioDevicePathField>(gpioConfig->second);
Matt Spinler8bc12832017-09-19 11:17:54 -0500357
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500358 // The /dev/gpiochipX device
Matt Spinler8bc12832017-09-19 11:17:54 -0500359 auto device = findGPIODevice(path);
360
Matt Spinler5c0ce172019-07-22 16:11:08 -0500361 if (device.empty())
362 {
363 log<level::ERR>(
364 "Missing GPIO device - cannot do GPIO analysis of fault",
365 entry("ANALYSIS_TYPE=%d\n", type));
366 return errorFound;
367 }
368
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500369 // The GPIO value of the fault condition
370 auto polarity = std::get<ucd90160::gpioPolarityField>(gpioConfig->second);
Matt Spinler8bc12832017-09-19 11:17:54 -0500371
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500372 // The GPIOs to check
373 auto& gpios = std::get<ucd90160::gpioDefinitionField>(gpioConfig->second);
Matt Spinler8bc12832017-09-19 11:17:54 -0500374
375 for (const auto& gpio : gpios)
376 {
377 gpio::Value value;
378
379 try
380 {
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500381 GPIO g{device, std::get<ucd90160::gpioNumField>(gpio),
Matt Spinler8bc12832017-09-19 11:17:54 -0500382 Direction::input};
383
384 value = g.read();
385 }
Patrick Williamsc1d4de52021-10-06 12:45:57 -0500386 catch (const std::exception& e)
Matt Spinler8bc12832017-09-19 11:17:54 -0500387 {
388 if (!gpioAccessError)
389 {
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500390 // GPIO only throws InternalErrors - not worth committing.
Matt Spinler8bc12832017-09-19 11:17:54 -0500391 log<level::ERR>(
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500392 "GPIO read failed while analyzing a power fault",
393 entry("CHIP_PATH=%s", path.c_str()));
Matt Spinler8bc12832017-09-19 11:17:54 -0500394
395 gpioAccessError = true;
396 }
397 continue;
398 }
399
400 if (value == polarity)
401 {
402 errorFound = true;
403
Matt Spinler0e45ced2018-02-12 14:36:07 -0600404 std::string part{INVENTORY_OBJ_PATH};
405 part = part + std::get<ucd90160::gpioCalloutField>(gpio);
Matt Spinler8bc12832017-09-19 11:17:54 -0500406 PartCallout callout{type, part};
407
408 if (isPartCalledOut(callout))
409 {
410 continue;
411 }
412
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500413 // Look up and call the error creation function
414 auto logError =
415 std::get<ucd90160::errorFunctionField>(gpioConfig->second);
Matt Spinler8bc12832017-09-19 11:17:54 -0500416
417 logError(*this, part);
418
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500419 // Save the part callout so we don't call it out again
Matt Spinler8bc12832017-09-19 11:17:54 -0500420 setPartCallout(callout);
Matt Spinlera8269652017-09-19 15:13:28 -0500421
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500422 // Some errors (like overtemps) require a shutdown
Matt Spinlera8269652017-09-19 15:13:28 -0500423 auto actions = static_cast<uint32_t>(
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500424 std::get<ucd90160::optionFlagsField>(gpioConfig->second));
Matt Spinlera8269652017-09-19 15:13:28 -0500425
426 if (actions & static_cast<decltype(actions)>(
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500427 ucd90160::optionFlags::shutdownOnFault))
Matt Spinlera8269652017-09-19 15:13:28 -0500428 {
429 shutdown = true;
430 }
Matt Spinler8bc12832017-09-19 11:17:54 -0500431 }
432 }
433
Matt Spinlera8269652017-09-19 15:13:28 -0500434 if (shutdown)
435 {
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500436 // Will be replaced with a GPU specific error in a future commit
Matt Spinler882ce952017-10-05 16:12:41 -0500437 util::powerOff<power_error::Shutdown>(bus);
Matt Spinlera8269652017-09-19 15:13:28 -0500438 }
439
Matt Spinler8bc12832017-09-19 11:17:54 -0500440 return errorFound;
441}
442
Matt Spinler7b14db22017-09-19 10:57:54 -0500443void UCD90160::gpuPGOODError(const std::string& callout)
444{
445 util::NamesValues nv;
Matt Spinler6def9092018-02-27 14:22:59 -0600446
447 try
448 {
449 nv.add("STATUS_WORD", readStatusWord());
450 nv.add("MFR_STATUS", readMFRStatus());
451 }
Patrick Williamsc1d4de52021-10-06 12:45:57 -0500452 catch (const device_error::ReadFailure& e)
Matt Spinler6def9092018-02-27 14:22:59 -0600453 {
454 log<level::ERR>("ReadFailure when collecting metadata");
455 commit<device_error::ReadFailure>();
456 }
Matt Spinler7b14db22017-09-19 10:57:54 -0500457
Brandon Wymane0eb45c2017-10-06 12:58:42 -0500458 using metadata = org::open_power::Witherspoon::Fault::GPUPowerFault;
Matt Spinler7b14db22017-09-19 10:57:54 -0500459
Matt Spinlerceacf942017-10-05 13:55:02 -0500460 report<power_error::GPUPowerFault>(
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500461 metadata::RAW_STATUS(nv.get().c_str()),
462 metadata::CALLOUT_INVENTORY_PATH(callout.c_str()));
Matt Spinler7b14db22017-09-19 10:57:54 -0500463}
464
465void UCD90160::gpuOverTempError(const std::string& callout)
466{
467 util::NamesValues nv;
Matt Spinler6def9092018-02-27 14:22:59 -0600468
469 try
470 {
471 nv.add("STATUS_WORD", readStatusWord());
472 nv.add("MFR_STATUS", readMFRStatus());
473 }
Patrick Williamsc1d4de52021-10-06 12:45:57 -0500474 catch (const device_error::ReadFailure& e)
Matt Spinler6def9092018-02-27 14:22:59 -0600475 {
476 log<level::ERR>("ReadFailure when collecting metadata");
477 commit<device_error::ReadFailure>();
478 }
Matt Spinler7b14db22017-09-19 10:57:54 -0500479
Brandon Wymane0eb45c2017-10-06 12:58:42 -0500480 using metadata = org::open_power::Witherspoon::Fault::GPUOverTemp;
Matt Spinler7b14db22017-09-19 10:57:54 -0500481
Matt Spinlerceacf942017-10-05 13:55:02 -0500482 report<power_error::GPUOverTemp>(
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500483 metadata::RAW_STATUS(nv.get().c_str()),
484 metadata::CALLOUT_INVENTORY_PATH(callout.c_str()));
Matt Spinler7b14db22017-09-19 10:57:54 -0500485}
486
Brandon Wyman03c19db2019-05-10 17:46:41 -0500487void UCD90160::memGoodError(const std::string& callout)
488{
489 util::NamesValues nv;
490
491 try
492 {
493 nv.add("STATUS_WORD", readStatusWord());
494 nv.add("MFR_STATUS", readMFRStatus());
495 }
Patrick Williamsc1d4de52021-10-06 12:45:57 -0500496 catch (const device_error::ReadFailure& e)
Brandon Wyman03c19db2019-05-10 17:46:41 -0500497 {
498 log<level::ERR>("ReadFailure when collecting metadata");
499 commit<device_error::ReadFailure>();
500 }
501
502 using metadata = org::open_power::Witherspoon::Fault::MemoryPowerFault;
503
504 report<power_error::MemoryPowerFault>(
505 metadata::RAW_STATUS(nv.get().c_str()),
506 metadata::CALLOUT_INVENTORY_PATH(callout.c_str()));
507}
508
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500509} // namespace power
Lei YUab093322019-10-09 16:43:22 +0800510} // namespace phosphor