1 /** 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 */ 16 #include "config.h" 17 18 #include "pgood_monitor.hpp" 19 20 #include "elog-errors.hpp" 21 #include "utility.hpp" 22 23 #include <org/open_power/Witherspoon/Fault/error.hpp> 24 #include <phosphor-logging/lg2.hpp> 25 26 namespace phosphor 27 { 28 namespace power 29 { 30 31 constexpr auto POWER_OBJ_PATH = "/org/openbmc/control/power0"; 32 constexpr auto POWER_INTERFACE = "org.openbmc.control.Power"; 33 34 using namespace sdbusplus::org::open_power::Witherspoon::Fault::Error; 35 36 bool PGOODMonitor::pgoodPending() 37 { 38 bool pending = false; 39 int32_t state = 0; 40 int32_t pgood = 0; 41 42 auto service = util::getService(POWER_OBJ_PATH, POWER_INTERFACE, bus); 43 44 util::getProperty<int32_t>(POWER_INTERFACE, "pgood", POWER_OBJ_PATH, 45 service, bus, pgood); 46 47 // When state = 1, system was switched on 48 util::getProperty<int32_t>(POWER_INTERFACE, "state", POWER_OBJ_PATH, 49 service, bus, state); 50 51 // On but no PGOOD 52 if (state && !pgood) 53 { 54 pending = true; 55 } 56 57 return pending; 58 } 59 60 void PGOODMonitor::analyze() 61 { 62 // Timer callback. 63 // The timer expired before it was stopped. 64 // If PGOOD is still pending (it should be), 65 // then there is a real failure. 66 67 if (pgoodPending()) 68 { 69 #ifdef DEVICE_ACCESS 70 device->onFailure(); 71 #endif 72 phosphor::logging::report<PowerOnFailure>(); 73 } 74 75 // The pgood-wait service (with a longer timeout) 76 // will handle powering off the system. 77 timer.get_event().exit(EXIT_SUCCESS); 78 } 79 80 void PGOODMonitor::propertyChanged() 81 { 82 // Multiple properties could have changed here. 83 // Keep things simple and just recheck the important ones. 84 if (!pgoodPending()) 85 { 86 // PGOOD is on, or system is off, so we are done. 87 timer.get_event().exit(EXIT_SUCCESS); 88 } 89 } 90 91 void PGOODMonitor::startListening() 92 { 93 match = std::make_unique<sdbusplus::bus::match_t>( 94 bus, 95 sdbusplus::bus::match::rules::propertiesChanged(POWER_OBJ_PATH, 96 POWER_INTERFACE), 97 [this](auto&) { this->propertyChanged(); }); 98 } 99 100 int PGOODMonitor::run() 101 { 102 try 103 { 104 startListening(); 105 106 // If PGOOD came up before we got here, we're done. 107 // Otherwise if PGOOD doesn't get asserted before 108 // the timer expires, it's a failure. 109 if (!pgoodPending()) 110 { 111 return EXIT_SUCCESS; 112 } 113 114 return timer.get_event().loop(); 115 } 116 catch (const std::exception& e) 117 { 118 lg2::error("Unexpected failure prevented PGOOD checking: {ERROR}", 119 "ERROR", e); 120 } 121 122 // Letting the service fail won't help anything, so don't do it. 123 return EXIT_SUCCESS; 124 } 125 126 } // namespace power 127 } // namespace phosphor 128