19284c307SShawn McCarney /**
29284c307SShawn McCarney * Copyright © 2021 IBM Corporation
39284c307SShawn McCarney *
49284c307SShawn McCarney * Licensed under the Apache License, Version 2.0 (the "License");
59284c307SShawn McCarney * you may not use this file except in compliance with the License.
69284c307SShawn McCarney * You may obtain a copy of the License at
79284c307SShawn McCarney *
89284c307SShawn McCarney * http://www.apache.org/licenses/LICENSE-2.0
99284c307SShawn McCarney *
109284c307SShawn McCarney * Unless required by applicable law or agreed to in writing, software
119284c307SShawn McCarney * distributed under the License is distributed on an "AS IS" BASIS,
129284c307SShawn McCarney * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139284c307SShawn McCarney * See the License for the specific language governing permissions and
149284c307SShawn McCarney * limitations under the License.
159284c307SShawn McCarney */
169284c307SShawn McCarney
179284c307SShawn McCarney #include "phase_fault_detection.hpp"
189284c307SShawn McCarney
199284c307SShawn McCarney #include "action_utils.hpp"
209284c307SShawn McCarney #include "chassis.hpp"
219284c307SShawn McCarney #include "device.hpp"
229284c307SShawn McCarney #include "error_logging.hpp"
239284c307SShawn McCarney #include "error_logging_utils.hpp"
249284c307SShawn McCarney #include "exception_utils.hpp"
259284c307SShawn McCarney #include "journal.hpp"
269284c307SShawn McCarney #include "system.hpp"
279284c307SShawn McCarney
289284c307SShawn McCarney #include <exception>
299284c307SShawn McCarney #include <map>
309284c307SShawn McCarney
319284c307SShawn McCarney namespace phosphor::power::regulators
329284c307SShawn McCarney {
339284c307SShawn McCarney
349284c307SShawn McCarney /**
359284c307SShawn McCarney * Maximum number of action errors to write to the journal.
369284c307SShawn McCarney */
379284c307SShawn McCarney constexpr unsigned short maxActionErrorCount{3};
389284c307SShawn McCarney
399284c307SShawn McCarney /**
409284c307SShawn McCarney * Number of consecutive phase faults required to log an error. This provides
419284c307SShawn McCarney * "de-glitching" to ignore transient hardware problems.
429284c307SShawn McCarney */
439284c307SShawn McCarney constexpr unsigned short requiredConsecutiveFaults{2};
449284c307SShawn McCarney
execute(Services & services,System & system,Chassis &,Device & regulator)459284c307SShawn McCarney void PhaseFaultDetection::execute(Services& services, System& system,
469284c307SShawn McCarney Chassis& /*chassis*/, Device& regulator)
479284c307SShawn McCarney {
489284c307SShawn McCarney try
499284c307SShawn McCarney {
509284c307SShawn McCarney // Find the device ID to use. If the deviceID data member is empty, use
519284c307SShawn McCarney // the ID of the specified regulator.
529284c307SShawn McCarney const std::string& effectiveDeviceID =
539284c307SShawn McCarney deviceID.empty() ? regulator.getID() : deviceID;
549284c307SShawn McCarney
559284c307SShawn McCarney // Create ActionEnvironment
569284c307SShawn McCarney ActionEnvironment environment{system.getIDMap(), effectiveDeviceID,
579284c307SShawn McCarney services};
589284c307SShawn McCarney
599284c307SShawn McCarney // Execute the actions to detect phase faults
609284c307SShawn McCarney action_utils::execute(actions, environment);
619284c307SShawn McCarney
629284c307SShawn McCarney // Check for any N or N+1 phase faults that were detected
639284c307SShawn McCarney checkForPhaseFault(PhaseFaultType::n, services, regulator, environment);
649284c307SShawn McCarney checkForPhaseFault(PhaseFaultType::n_plus_1, services, regulator,
659284c307SShawn McCarney environment);
669284c307SShawn McCarney }
679284c307SShawn McCarney catch (const std::exception& e)
689284c307SShawn McCarney {
699284c307SShawn McCarney // Log error messages in journal if we haven't hit the max
709284c307SShawn McCarney if (actionErrorCount < maxActionErrorCount)
719284c307SShawn McCarney {
729284c307SShawn McCarney ++actionErrorCount;
739284c307SShawn McCarney services.getJournal().logError(exception_utils::getMessages(e));
749284c307SShawn McCarney services.getJournal().logError(
759284c307SShawn McCarney "Unable to detect phase faults in regulator " +
769284c307SShawn McCarney regulator.getID());
779284c307SShawn McCarney }
789284c307SShawn McCarney
799284c307SShawn McCarney // Create error log entry if this type hasn't already been logged
809284c307SShawn McCarney error_logging_utils::logError(std::current_exception(),
819284c307SShawn McCarney Entry::Level::Warning, services,
829284c307SShawn McCarney errorHistory);
839284c307SShawn McCarney }
849284c307SShawn McCarney }
859284c307SShawn McCarney
checkForPhaseFault(PhaseFaultType faultType,Services & services,Device & regulator,ActionEnvironment & environment)86*f5402197SPatrick Williams void PhaseFaultDetection::checkForPhaseFault(
87*f5402197SPatrick Williams PhaseFaultType faultType, Services& services, Device& regulator,
889284c307SShawn McCarney ActionEnvironment& environment)
899284c307SShawn McCarney {
909284c307SShawn McCarney // Find ErrorType that corresponds to PhaseFaultType; used by ErrorHistory
919284c307SShawn McCarney ErrorType errorType = toErrorType(faultType);
929284c307SShawn McCarney
939284c307SShawn McCarney // If this error has not been logged yet
949284c307SShawn McCarney if (!errorHistory.wasLogged(errorType))
959284c307SShawn McCarney {
969284c307SShawn McCarney // Create reference to consecutive fault count data member
979284c307SShawn McCarney unsigned short& faultCount =
989284c307SShawn McCarney (faultType == PhaseFaultType::n) ? nFaultCount : nPlus1FaultCount;
999284c307SShawn McCarney
1009284c307SShawn McCarney // Check if the phase fault was detected
1019284c307SShawn McCarney if (environment.getPhaseFaults().count(faultType) == 0)
1029284c307SShawn McCarney {
1039284c307SShawn McCarney // Phase fault not detected; reset consecutive fault count
1049284c307SShawn McCarney faultCount = 0;
1059284c307SShawn McCarney }
1069284c307SShawn McCarney else
1079284c307SShawn McCarney {
1089284c307SShawn McCarney // Phase fault detected; increment consecutive fault count
1099284c307SShawn McCarney ++faultCount;
1109284c307SShawn McCarney
1119284c307SShawn McCarney // Log error message in journal
1129284c307SShawn McCarney services.getJournal().logError(
1139284c307SShawn McCarney toString(faultType) + " phase fault detected in regulator " +
1149284c307SShawn McCarney regulator.getID() + ": count=" + std::to_string(faultCount));
1159284c307SShawn McCarney
1169284c307SShawn McCarney // If the required number of consecutive faults have been detected
1179284c307SShawn McCarney if (faultCount >= requiredConsecutiveFaults)
1189284c307SShawn McCarney {
1199284c307SShawn McCarney // Log phase fault error and update ErrorHistory
1209284c307SShawn McCarney logPhaseFault(faultType, services, regulator, environment);
1219284c307SShawn McCarney errorHistory.setWasLogged(errorType, true);
1229284c307SShawn McCarney }
1239284c307SShawn McCarney }
1249284c307SShawn McCarney }
1259284c307SShawn McCarney }
1269284c307SShawn McCarney
logPhaseFault(PhaseFaultType faultType,Services & services,Device & regulator,ActionEnvironment & environment)1279284c307SShawn McCarney void PhaseFaultDetection::logPhaseFault(PhaseFaultType faultType,
1289284c307SShawn McCarney Services& services, Device& regulator,
1299284c307SShawn McCarney ActionEnvironment& environment)
1309284c307SShawn McCarney {
1319284c307SShawn McCarney ErrorLogging& errorLogging = services.getErrorLogging();
1329284c307SShawn McCarney Entry::Level severity = (faultType == PhaseFaultType::n)
1339284c307SShawn McCarney ? Entry::Level::Warning
1349284c307SShawn McCarney : Entry::Level::Informational;
1359284c307SShawn McCarney Journal& journal = services.getJournal();
1369284c307SShawn McCarney const std::string& inventoryPath = regulator.getFRU();
1379284c307SShawn McCarney const std::map<std::string, std::string>& additionalData =
1389284c307SShawn McCarney environment.getAdditionalErrorData();
1399284c307SShawn McCarney errorLogging.logPhaseFault(severity, journal, faultType, inventoryPath,
1409284c307SShawn McCarney additionalData);
1419284c307SShawn McCarney }
1429284c307SShawn McCarney
1439284c307SShawn McCarney } // namespace phosphor::power::regulators
144