blob: 8d28a323dca019d9076cc0665afb2122c095c2da [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
Matt Spinlera8269652017-09-19 15:13:28 -050053UCD90160::UCD90160(size_t instance, sdbusplus::bus::bus& 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)
Matt Spinlerb54357f2017-08-21 14:38:54 -050058{
59}
60
61void UCD90160::onFailure()
62{
63 try
64 {
65 auto voutError = checkVOUTFaults();
66
67 auto pgoodError = checkPGOODFaults(false);
68
Matt Spinlerf0f02b92018-10-25 16:12:43 -050069 // Not a voltage or PGOOD fault, but we know something
70 // failed so still create an error log.
Matt Spinlerb54357f2017-08-21 14:38:54 -050071 if (!voutError && !pgoodError)
72 {
73 createPowerFaultLog();
74 }
75 }
Matt Spinlerceacf942017-10-05 13:55:02 -050076 catch (device_error::ReadFailure& e)
Matt Spinlerb54357f2017-08-21 14:38:54 -050077 {
78 if (!accessError)
79 {
Matt Spinlerceacf942017-10-05 13:55:02 -050080 commit<device_error::ReadFailure>();
Matt Spinlerb54357f2017-08-21 14:38:54 -050081 accessError = true;
82 }
83 }
84}
85
86void UCD90160::analyze()
87{
88 try
89 {
Matt Spinlerf0f02b92018-10-25 16:12:43 -050090 // Note: Voltage faults are always fatal, so they just
91 // need to be analyzed in onFailure().
Matt Spinlerb54357f2017-08-21 14:38:54 -050092
93 checkPGOODFaults(true);
94 }
Matt Spinlerceacf942017-10-05 13:55:02 -050095 catch (device_error::ReadFailure& e)
Matt Spinlerb54357f2017-08-21 14:38:54 -050096 {
97 if (!accessError)
98 {
Matt Spinlerceacf942017-10-05 13:55:02 -050099 commit<device_error::ReadFailure>();
Matt Spinlerb54357f2017-08-21 14:38:54 -0500100 accessError = true;
101 }
102 }
103}
104
Matt Spinlere7e432b2017-08-21 15:01:40 -0500105uint16_t UCD90160::readStatusWord()
106{
107 return interface.read(STATUS_WORD, Type::Debug);
108}
109
110uint32_t UCD90160::readMFRStatus()
111{
Matt Spinler233a2522018-03-30 14:40:04 -0500112 return interface.read(MFR_STATUS, Type::HwmonDeviceDebug);
Matt Spinlere7e432b2017-08-21 15:01:40 -0500113}
114
Matt Spinlerb54357f2017-08-21 14:38:54 -0500115bool UCD90160::checkVOUTFaults()
116{
Matt Spinlere7e432b2017-08-21 15:01:40 -0500117 bool errorCreated = false;
118 auto statusWord = readStatusWord();
119
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500120 // The status_word register has a summary bit to tell us
121 // if each page even needs to be checked
Matt Spinlere7e432b2017-08-21 15:01:40 -0500122 if (!(statusWord & status_word::VOUT_FAULT))
123 {
124 return errorCreated;
125 }
126
127 for (size_t page = 0; page < NUM_PAGES; page++)
128 {
129 if (isVoutFaultLogged(page))
130 {
131 continue;
132 }
133
134 auto statusVout = interface.insertPageNum(STATUS_VOUT, page);
135 uint8_t vout = interface.read(statusVout, Type::Debug);
136
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500137 // If any bits are on log them, though some are just
138 // warnings so they won't cause errors
Matt Spinlere7e432b2017-08-21 15:01:40 -0500139 if (vout)
140 {
Matt Spinlerde16d052017-12-13 13:22:14 -0600141 log<level::INFO>("A voltage rail has bits on in STATUS_VOUT",
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500142 entry("STATUS_VOUT=0x%X", vout),
143 entry("PAGE=%d", page));
Matt Spinlerde16d052017-12-13 13:22:14 -0600144 }
145
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500146 // Log errors if any non-warning bits on
Matt Spinlerde16d052017-12-13 13:22:14 -0600147 if (vout & ~status_vout::WARNING_MASK)
148 {
Matt Spinlere7e432b2017-08-21 15:01:40 -0500149 auto& railNames = std::get<ucd90160::railNamesField>(
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500150 deviceMap.find(getInstance())->second);
Matt Spinlere7e432b2017-08-21 15:01:40 -0500151 auto railName = railNames.at(page);
152
153 util::NamesValues nv;
Matt Spinler6def9092018-02-27 14:22:59 -0600154 try
155 {
156 nv.add("STATUS_WORD", statusWord);
157 nv.add("STATUS_VOUT", vout);
158 nv.add("MFR_STATUS", readMFRStatus());
159 }
160 catch (device_error::ReadFailure& e)
161 {
162 log<level::ERR>("ReadFailure when collecting metadata");
163 commit<device_error::ReadFailure>();
164 }
Matt Spinlere7e432b2017-08-21 15:01:40 -0500165
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500166 using metadata =
167 org::open_power::Witherspoon::Fault::PowerSequencerVoltageFault;
Matt Spinlere7e432b2017-08-21 15:01:40 -0500168
Matt Spinlerceacf942017-10-05 13:55:02 -0500169 report<power_error::PowerSequencerVoltageFault>(
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500170 metadata::RAIL(page), metadata::RAIL_NAME(railName.c_str()),
171 metadata::RAW_STATUS(nv.get().c_str()));
Matt Spinlere7e432b2017-08-21 15:01:40 -0500172
173 setVoutFaultLogged(page);
174 errorCreated = true;
175 }
176 }
177
178 return errorCreated;
Matt Spinlerb54357f2017-08-21 14:38:54 -0500179}
180
181bool UCD90160::checkPGOODFaults(bool polling)
182{
Matt Spinlerd998b732017-08-21 15:35:54 -0500183 bool errorCreated = false;
184
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500185 // While PGOOD faults could show up in MFR_STATUS (and we could then
186 // check the summary bit in STATUS_WORD first), they are edge triggered,
187 // and as the device driver sends a clear faults command every time we
188 // do a read, we will never see them. So, we'll have to just read the
189 // real time GPI status GPIO.
Matt Spinlerd998b732017-08-21 15:35:54 -0500190
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500191 // Check only the GPIs configured on this system.
Matt Spinlerd998b732017-08-21 15:35:54 -0500192 auto& gpiConfigs = std::get<ucd90160::gpiConfigField>(
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500193 deviceMap.find(getInstance())->second);
Matt Spinlerd998b732017-08-21 15:35:54 -0500194
195 for (const auto& gpiConfig : gpiConfigs)
196 {
197 auto gpiNum = std::get<ucd90160::gpiNumField>(gpiConfig);
198 auto doPoll = std::get<ucd90160::pollField>(gpiConfig);
199
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500200 // Can skip this one if there is already an error on this input,
201 // or we are polling and these inputs don't need to be polled
Matt Spinlerd998b732017-08-21 15:35:54 -0500202 //(because errors on them are fatal).
203 if (isPGOODFaultLogged(gpiNum) || (polling && !doPoll))
204 {
205 continue;
206 }
207
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500208 // The real time status is read via the pin ID
Matt Spinlerd998b732017-08-21 15:35:54 -0500209 auto pinID = std::get<ucd90160::pinIDField>(gpiConfig);
210 auto gpio = gpios.find(pinID);
211 Value gpiStatus;
212
213 try
214 {
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500215 // The first time through, create the GPIO objects
Matt Spinlerd998b732017-08-21 15:35:54 -0500216 if (gpio == gpios.end())
217 {
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500218 gpios.emplace(pinID, std::make_unique<GPIO>(gpioDevice, pinID,
219 Direction::input));
Matt Spinlerd998b732017-08-21 15:35:54 -0500220 gpio = gpios.find(pinID);
221 }
222
223 gpiStatus = gpio->second->read();
224 }
225 catch (std::exception& e)
226 {
227 if (!accessError)
228 {
229 log<level::ERR>(e.what());
230 accessError = true;
231 }
232 continue;
233 }
234
235 if (gpiStatus == Value::low)
236 {
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500237 // There may be some extra analysis we can do to narrow the
238 // error down further. Note that finding an error here won't
239 // prevent us from checking this GPI again.
Matt Spinler8bc12832017-09-19 11:17:54 -0500240 errorCreated = doExtraAnalysis(gpiConfig);
241
242 if (errorCreated)
243 {
244 continue;
245 }
246
Matt Spinlerd998b732017-08-21 15:35:54 -0500247 auto& gpiName = std::get<ucd90160::gpiNameField>(gpiConfig);
248 auto status = (gpiStatus == Value::low) ? 0 : 1;
249
250 util::NamesValues nv;
Matt Spinler6def9092018-02-27 14:22:59 -0600251
252 try
253 {
254 nv.add("STATUS_WORD", readStatusWord());
255 nv.add("MFR_STATUS", readMFRStatus());
256 nv.add("INPUT_STATUS", status);
257 }
258 catch (device_error::ReadFailure& e)
259 {
260 log<level::ERR>("ReadFailure when collecting metadata");
261 commit<device_error::ReadFailure>();
262 }
Matt Spinlerd998b732017-08-21 15:35:54 -0500263
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500264 using metadata =
265 org::open_power::Witherspoon::Fault::PowerSequencerPGOODFault;
Matt Spinlerd998b732017-08-21 15:35:54 -0500266
Matt Spinlerceacf942017-10-05 13:55:02 -0500267 report<power_error::PowerSequencerPGOODFault>(
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500268 metadata::INPUT_NUM(gpiNum),
269 metadata::INPUT_NAME(gpiName.c_str()),
270 metadata::RAW_STATUS(nv.get().c_str()));
Matt Spinlerd998b732017-08-21 15:35:54 -0500271
272 setPGOODFaultLogged(gpiNum);
273 errorCreated = true;
274 }
275 }
276
277 return errorCreated;
Matt Spinlerb54357f2017-08-21 14:38:54 -0500278}
279
280void UCD90160::createPowerFaultLog()
281{
Matt Spinler9efb3082017-08-21 15:43:43 -0500282 util::NamesValues nv;
Matt Spinler6def9092018-02-27 14:22:59 -0600283
284 try
285 {
286 nv.add("STATUS_WORD", readStatusWord());
287 nv.add("MFR_STATUS", readMFRStatus());
288 }
289 catch (device_error::ReadFailure& e)
290 {
291 log<level::ERR>("ReadFailure when collecting metadata");
292 commit<device_error::ReadFailure>();
293 }
Matt Spinlerb54357f2017-08-21 14:38:54 -0500294
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500295 using metadata = org::open_power::Witherspoon::Fault::PowerSequencerFault;
Matt Spinler9efb3082017-08-21 15:43:43 -0500296
Matt Spinlerceacf942017-10-05 13:55:02 -0500297 report<power_error::PowerSequencerFault>(
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500298 metadata::RAW_STATUS(nv.get().c_str()));
Matt Spinlerb54357f2017-08-21 14:38:54 -0500299}
300
Matt Spinlerfcd4a712017-09-19 10:45:07 -0500301fs::path UCD90160::findGPIODevice(const fs::path& path)
Matt Spinler110b2842017-08-21 15:23:27 -0500302{
Matt Spinlerfcd4a712017-09-19 10:45:07 -0500303 fs::path gpioDevicePath;
Matt Spinler110b2842017-08-21 15:23:27 -0500304
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500305 // In the driver directory, look for a subdirectory
306 // named gpiochipX, where X is some number. Then
307 // we'll access the GPIO at /dev/gpiochipX.
Matt Spinler110b2842017-08-21 15:23:27 -0500308 if (fs::is_directory(path))
309 {
310 for (auto& f : fs::directory_iterator(path))
311 {
312 if (f.path().filename().string().find("gpiochip") !=
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500313 std::string::npos)
Matt Spinler110b2842017-08-21 15:23:27 -0500314 {
Matt Spinlerfcd4a712017-09-19 10:45:07 -0500315 gpioDevicePath = "/dev" / f.path().filename();
Matt Spinler110b2842017-08-21 15:23:27 -0500316 break;
317 }
318 }
319 }
320
Matt Spinlerfcd4a712017-09-19 10:45:07 -0500321 if (gpioDevicePath.empty())
Matt Spinler110b2842017-08-21 15:23:27 -0500322 {
Matt Spinlerfcd4a712017-09-19 10:45:07 -0500323 log<level::ERR>("Could not find GPIO device path",
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500324 entry("BASE_PATH=%s", path.c_str()));
Matt Spinler110b2842017-08-21 15:23:27 -0500325 }
Matt Spinlerfcd4a712017-09-19 10:45:07 -0500326
327 return gpioDevicePath;
Matt Spinler110b2842017-08-21 15:23:27 -0500328}
329
Matt Spinler8bc12832017-09-19 11:17:54 -0500330bool UCD90160::doExtraAnalysis(const ucd90160::GPIConfig& config)
331{
332
333 auto type = std::get<ucd90160::extraAnalysisField>(config);
334 if (type == ucd90160::extraAnalysisType::none)
335 {
336 return false;
337 }
338
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500339 // Currently the only extra analysis to do is to check other GPIOs.
Matt Spinler8bc12832017-09-19 11:17:54 -0500340 return doGPIOAnalysis(type);
341}
342
343bool UCD90160::doGPIOAnalysis(ucd90160::extraAnalysisType type)
344{
345 bool errorFound = false;
Matt Spinlera8269652017-09-19 15:13:28 -0500346 bool shutdown = false;
Matt Spinler8bc12832017-09-19 11:17:54 -0500347
348 const auto& analysisConfig = std::get<ucd90160::gpioAnalysisField>(
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500349 deviceMap.find(getInstance())->second);
Matt Spinler8bc12832017-09-19 11:17:54 -0500350
351 auto gpioConfig = analysisConfig.find(type);
352 if (gpioConfig == analysisConfig.end())
353 {
354 return errorFound;
355 }
356
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500357 auto path = std::get<ucd90160::gpioDevicePathField>(gpioConfig->second);
Matt Spinler8bc12832017-09-19 11:17:54 -0500358
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500359 // The /dev/gpiochipX device
Matt Spinler8bc12832017-09-19 11:17:54 -0500360 auto device = findGPIODevice(path);
361
Matt Spinler5c0ce172019-07-22 16:11:08 -0500362 if (device.empty())
363 {
364 log<level::ERR>(
365 "Missing GPIO device - cannot do GPIO analysis of fault",
366 entry("ANALYSIS_TYPE=%d\n", type));
367 return errorFound;
368 }
369
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500370 // The GPIO value of the fault condition
371 auto polarity = std::get<ucd90160::gpioPolarityField>(gpioConfig->second);
Matt Spinler8bc12832017-09-19 11:17:54 -0500372
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500373 // The GPIOs to check
374 auto& gpios = std::get<ucd90160::gpioDefinitionField>(gpioConfig->second);
Matt Spinler8bc12832017-09-19 11:17:54 -0500375
376 for (const auto& gpio : gpios)
377 {
378 gpio::Value value;
379
380 try
381 {
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500382 GPIO g{device, std::get<ucd90160::gpioNumField>(gpio),
Matt Spinler8bc12832017-09-19 11:17:54 -0500383 Direction::input};
384
385 value = g.read();
386 }
387 catch (std::exception& e)
388 {
389 if (!gpioAccessError)
390 {
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500391 // GPIO only throws InternalErrors - not worth committing.
Matt Spinler8bc12832017-09-19 11:17:54 -0500392 log<level::ERR>(
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500393 "GPIO read failed while analyzing a power fault",
394 entry("CHIP_PATH=%s", path.c_str()));
Matt Spinler8bc12832017-09-19 11:17:54 -0500395
396 gpioAccessError = true;
397 }
398 continue;
399 }
400
401 if (value == polarity)
402 {
403 errorFound = true;
404
Matt Spinler0e45ced2018-02-12 14:36:07 -0600405 std::string part{INVENTORY_OBJ_PATH};
406 part = part + std::get<ucd90160::gpioCalloutField>(gpio);
Matt Spinler8bc12832017-09-19 11:17:54 -0500407 PartCallout callout{type, part};
408
409 if (isPartCalledOut(callout))
410 {
411 continue;
412 }
413
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500414 // Look up and call the error creation function
415 auto logError =
416 std::get<ucd90160::errorFunctionField>(gpioConfig->second);
Matt Spinler8bc12832017-09-19 11:17:54 -0500417
418 logError(*this, part);
419
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500420 // Save the part callout so we don't call it out again
Matt Spinler8bc12832017-09-19 11:17:54 -0500421 setPartCallout(callout);
Matt Spinlera8269652017-09-19 15:13:28 -0500422
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500423 // Some errors (like overtemps) require a shutdown
Matt Spinlera8269652017-09-19 15:13:28 -0500424 auto actions = static_cast<uint32_t>(
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500425 std::get<ucd90160::optionFlagsField>(gpioConfig->second));
Matt Spinlera8269652017-09-19 15:13:28 -0500426
427 if (actions & static_cast<decltype(actions)>(
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500428 ucd90160::optionFlags::shutdownOnFault))
Matt Spinlera8269652017-09-19 15:13:28 -0500429 {
430 shutdown = true;
431 }
Matt Spinler8bc12832017-09-19 11:17:54 -0500432 }
433 }
434
Matt Spinlera8269652017-09-19 15:13:28 -0500435 if (shutdown)
436 {
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500437 // Will be replaced with a GPU specific error in a future commit
Matt Spinler882ce952017-10-05 16:12:41 -0500438 util::powerOff<power_error::Shutdown>(bus);
Matt Spinlera8269652017-09-19 15:13:28 -0500439 }
440
Matt Spinler8bc12832017-09-19 11:17:54 -0500441 return errorFound;
442}
443
Matt Spinler7b14db22017-09-19 10:57:54 -0500444void UCD90160::gpuPGOODError(const std::string& callout)
445{
446 util::NamesValues nv;
Matt Spinler6def9092018-02-27 14:22:59 -0600447
448 try
449 {
450 nv.add("STATUS_WORD", readStatusWord());
451 nv.add("MFR_STATUS", readMFRStatus());
452 }
453 catch (device_error::ReadFailure& e)
454 {
455 log<level::ERR>("ReadFailure when collecting metadata");
456 commit<device_error::ReadFailure>();
457 }
Matt Spinler7b14db22017-09-19 10:57:54 -0500458
Brandon Wymane0eb45c2017-10-06 12:58:42 -0500459 using metadata = org::open_power::Witherspoon::Fault::GPUPowerFault;
Matt Spinler7b14db22017-09-19 10:57:54 -0500460
Matt Spinlerceacf942017-10-05 13:55:02 -0500461 report<power_error::GPUPowerFault>(
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500462 metadata::RAW_STATUS(nv.get().c_str()),
463 metadata::CALLOUT_INVENTORY_PATH(callout.c_str()));
Matt Spinler7b14db22017-09-19 10:57:54 -0500464}
465
466void UCD90160::gpuOverTempError(const std::string& callout)
467{
468 util::NamesValues nv;
Matt Spinler6def9092018-02-27 14:22:59 -0600469
470 try
471 {
472 nv.add("STATUS_WORD", readStatusWord());
473 nv.add("MFR_STATUS", readMFRStatus());
474 }
475 catch (device_error::ReadFailure& e)
476 {
477 log<level::ERR>("ReadFailure when collecting metadata");
478 commit<device_error::ReadFailure>();
479 }
Matt Spinler7b14db22017-09-19 10:57:54 -0500480
Brandon Wymane0eb45c2017-10-06 12:58:42 -0500481 using metadata = org::open_power::Witherspoon::Fault::GPUOverTemp;
Matt Spinler7b14db22017-09-19 10:57:54 -0500482
Matt Spinlerceacf942017-10-05 13:55:02 -0500483 report<power_error::GPUOverTemp>(
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500484 metadata::RAW_STATUS(nv.get().c_str()),
485 metadata::CALLOUT_INVENTORY_PATH(callout.c_str()));
Matt Spinler7b14db22017-09-19 10:57:54 -0500486}
487
Brandon Wyman03c19db2019-05-10 17:46:41 -0500488void UCD90160::memGoodError(const std::string& callout)
489{
490 util::NamesValues nv;
491
492 try
493 {
494 nv.add("STATUS_WORD", readStatusWord());
495 nv.add("MFR_STATUS", readMFRStatus());
496 }
497 catch (device_error::ReadFailure& e)
498 {
499 log<level::ERR>("ReadFailure when collecting metadata");
500 commit<device_error::ReadFailure>();
501 }
502
503 using metadata = org::open_power::Witherspoon::Fault::MemoryPowerFault;
504
505 report<power_error::MemoryPowerFault>(
506 metadata::RAW_STATUS(nv.get().c_str()),
507 metadata::CALLOUT_INVENTORY_PATH(callout.c_str()));
508}
509
Matt Spinlerf0f02b92018-10-25 16:12:43 -0500510} // namespace power
Lei YUab093322019-10-09 16:43:22 +0800511} // namespace phosphor