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