blob: a11a9cc6a4c4158990e59a39b1082b0211ac98d5 [file] [log] [blame]
Shawn McCarney472101c2024-04-17 16:31:09 -05001/**
2 * Copyright © 2024 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 */
16
17#include "standard_device.hpp"
18
19#include "format_utils.hpp"
20
21#include <exception>
22#include <format>
23#include <span>
24#include <stdexcept>
25
26namespace phosphor::power::sequencer
27{
28
29std::string StandardDevice::findPgoodFault(
30 Services& services, const std::string& powerSupplyError,
31 std::map<std::string, std::string>& additionalData)
32{
33 std::string error{};
34 try
35 {
36 prepareForPgoodFaultDetection(services);
37
38 // Get all GPIO values (if possible) from device. They may be slow to
39 // obtain, so obtain them once and then pass values to each Rail object.
Shawn McCarneyfc3f31f2024-04-23 17:02:44 -050040 std::vector<int> gpioValues = getGPIOValuesIfPossible(services);
Shawn McCarney472101c2024-04-17 16:31:09 -050041
42 // Loop through all the rails checking if any detected a pgood fault.
43 // The rails are in power-on-sequence order.
44 for (std::unique_ptr<Rail>& rail : rails)
45 {
46 if (rail->hasPgoodFault(*this, services, gpioValues,
47 additionalData))
48 {
49 services.logErrorMsg(std::format(
50 "Pgood fault found in rail monitored by device {}", name));
51
52 // If this is a PSU rail and a PSU error was previously detected
53 if (rail->isPowerSupplyRail() && !powerSupplyError.empty())
54 {
55 // Return power supply error as root cause
56 error = powerSupplyError;
57 }
58 else
59 {
60 // Return pgood fault as root cause
61 error =
62 "xyz.openbmc_project.Power.Error.PowerSequencerVoltageFault";
63 }
64
65 storePgoodFaultDebugData(services, gpioValues, additionalData);
66 break;
67 }
68 }
69 }
70 catch (const std::exception& e)
71 {
72 throw std::runtime_error{std::format(
73 "Unable to determine if a pgood fault occurred in device {}: {}",
74 name, e.what())};
75 }
76 return error;
77}
78
Shawn McCarneyfc3f31f2024-04-23 17:02:44 -050079std::vector<int> StandardDevice::getGPIOValuesIfPossible(Services& services)
Shawn McCarney472101c2024-04-17 16:31:09 -050080{
81 std::vector<int> values{};
82 try
83 {
Shawn McCarneyfc3f31f2024-04-23 17:02:44 -050084 values = getGPIOValues(services);
Shawn McCarney472101c2024-04-17 16:31:09 -050085 }
86 catch (...)
87 {}
88 return values;
89}
90
91void StandardDevice::storePgoodFaultDebugData(
92 Services& services, const std::vector<int>& gpioValues,
93 std::map<std::string, std::string>& additionalData)
94{
Shawn McCarneyfe78c172024-05-02 14:01:46 -050095 try
Shawn McCarney472101c2024-04-17 16:31:09 -050096 {
Shawn McCarneyfe78c172024-05-02 14:01:46 -050097 additionalData.emplace("DEVICE_NAME", name);
98 storeGPIOValues(services, gpioValues, additionalData);
99 }
100 catch (...)
101 {}
102}
103
104void StandardDevice::storeGPIOValues(
105 Services& services, const std::vector<int>& values,
106 std::map<std::string, std::string>& additionalData)
107{
108 if (!values.empty())
109 {
110 std::string valuesStr = format_utils::toString(std::span(values));
Shawn McCarney472101c2024-04-17 16:31:09 -0500111 services.logInfoMsg(
112 std::format("Device {} GPIO values: {}", name, valuesStr));
113 additionalData.emplace("GPIO_VALUES", valuesStr);
114 }
115}
116
117} // namespace phosphor::power::sequencer