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