1f02daec1SMatt Spinler /** 2f02daec1SMatt Spinler * Copyright © 2017 IBM Corporation 3f02daec1SMatt Spinler * 4f02daec1SMatt Spinler * Licensed under the Apache License, Version 2.0 (the "License"); 5f02daec1SMatt Spinler * you may not use this file except in compliance with the License. 6f02daec1SMatt Spinler * You may obtain a copy of the License at 7f02daec1SMatt Spinler * 8f02daec1SMatt Spinler * http://www.apache.org/licenses/LICENSE-2.0 9f02daec1SMatt Spinler * 10f02daec1SMatt Spinler * Unless required by applicable law or agreed to in writing, software 11f02daec1SMatt Spinler * distributed under the License is distributed on an "AS IS" BASIS, 12f02daec1SMatt Spinler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f02daec1SMatt Spinler * See the License for the specific language governing permissions and 14f02daec1SMatt Spinler * limitations under the License. 15f02daec1SMatt Spinler */ 1645a054acSMatt Spinler #include "config.h" 17f0f02b9aSMatt Spinler 18f02daec1SMatt Spinler #include "pgood_monitor.hpp" 19f0f02b9aSMatt Spinler 20f0f02b9aSMatt Spinler #include "elog-errors.hpp" 21f02daec1SMatt Spinler #include "utility.hpp" 22f02daec1SMatt Spinler 23f0f02b9aSMatt Spinler #include <org/open_power/Witherspoon/Fault/error.hpp> 24f0f02b9aSMatt Spinler #include <phosphor-logging/log.hpp> 25f0f02b9aSMatt Spinler 26f02daec1SMatt Spinler namespace witherspoon 27f02daec1SMatt Spinler { 28f02daec1SMatt Spinler namespace power 29f02daec1SMatt Spinler { 30f02daec1SMatt Spinler 31f02daec1SMatt Spinler constexpr auto POWER_OBJ_PATH = "/org/openbmc/control/power0"; 32f02daec1SMatt Spinler constexpr auto POWER_INTERFACE = "org.openbmc.control.Power"; 33f02daec1SMatt Spinler 34f02daec1SMatt Spinler using namespace phosphor::logging; 35e0eb45ccSBrandon Wyman using namespace sdbusplus::org::open_power::Witherspoon::Fault::Error; 36f02daec1SMatt Spinler 37f02daec1SMatt Spinler bool PGOODMonitor::pgoodPending() 38f02daec1SMatt Spinler { 39f02daec1SMatt Spinler bool pending = false; 40f02daec1SMatt Spinler int32_t state = 0; 41f02daec1SMatt Spinler int32_t pgood = 0; 42f02daec1SMatt Spinler 43f0f02b9aSMatt Spinler auto service = util::getService(POWER_OBJ_PATH, POWER_INTERFACE, bus); 44f02daec1SMatt Spinler 45f0f02b9aSMatt Spinler util::getProperty<int32_t>(POWER_INTERFACE, "pgood", POWER_OBJ_PATH, 46f0f02b9aSMatt Spinler service, bus, pgood); 47f02daec1SMatt Spinler 48f02daec1SMatt Spinler // When state = 1, system was switched on 49f0f02b9aSMatt Spinler util::getProperty<int32_t>(POWER_INTERFACE, "state", POWER_OBJ_PATH, 50f0f02b9aSMatt Spinler service, bus, state); 51f02daec1SMatt Spinler 52f02daec1SMatt Spinler // On but no PGOOD 53f02daec1SMatt Spinler if (state && !pgood) 54f02daec1SMatt Spinler { 55f02daec1SMatt Spinler pending = true; 56f02daec1SMatt Spinler } 57f02daec1SMatt Spinler 58f02daec1SMatt Spinler return pending; 59f02daec1SMatt Spinler } 60f02daec1SMatt Spinler 61f02daec1SMatt Spinler void PGOODMonitor::analyze() 62f02daec1SMatt Spinler { 63f02daec1SMatt Spinler // Timer callback. 64f02daec1SMatt Spinler // The timer expired before it was stopped. 65f02daec1SMatt Spinler // If PGOOD is still pending (it should be), 66f02daec1SMatt Spinler // then there is a real failure. 67f02daec1SMatt Spinler 68f02daec1SMatt Spinler if (pgoodPending()) 69f02daec1SMatt Spinler { 7045a054acSMatt Spinler #ifdef UCD90160_DEVICE_ACCESS 71b2d72511SMatt Spinler device->onFailure(); 7245a054acSMatt Spinler #endif 73f02daec1SMatt Spinler report<PowerOnFailure>(); 74f02daec1SMatt Spinler } 75f02daec1SMatt Spinler 76f02daec1SMatt Spinler // The pgood-wait service (with a longer timeout) 77f02daec1SMatt Spinler // will handle powering off the system. 781a0c9176SWilliam A. Kennington III timer.get_event().exit(EXIT_SUCCESS); 79f02daec1SMatt Spinler } 80f02daec1SMatt Spinler 81f02daec1SMatt Spinler void PGOODMonitor::propertyChanged() 82f02daec1SMatt Spinler { 83f02daec1SMatt Spinler // Multiple properties could have changed here. 84f02daec1SMatt Spinler // Keep things simple and just recheck the important ones. 85f02daec1SMatt Spinler if (!pgoodPending()) 86f02daec1SMatt Spinler { 87f02daec1SMatt Spinler // PGOOD is on, or system is off, so we are done. 881a0c9176SWilliam A. Kennington III timer.get_event().exit(EXIT_SUCCESS); 89f02daec1SMatt Spinler } 90f02daec1SMatt Spinler } 91f02daec1SMatt Spinler 92f02daec1SMatt Spinler void PGOODMonitor::startListening() 93f02daec1SMatt Spinler { 94f02daec1SMatt Spinler match = std::make_unique<sdbusplus::bus::match_t>( 95f02daec1SMatt Spinler bus, 96f0f02b9aSMatt Spinler sdbusplus::bus::match::rules::propertiesChanged(POWER_OBJ_PATH, 97f02daec1SMatt Spinler POWER_INTERFACE), 98*11cb6728SBrad Bishop [this](auto&) { this->propertyChanged(); }); 99f02daec1SMatt Spinler } 100f02daec1SMatt Spinler 101f02daec1SMatt Spinler int PGOODMonitor::run() 102f02daec1SMatt Spinler { 103f02daec1SMatt Spinler try 104f02daec1SMatt Spinler { 105f02daec1SMatt Spinler startListening(); 106f02daec1SMatt Spinler 107f02daec1SMatt Spinler // If PGOOD came up before we got here, we're done. 108f02daec1SMatt Spinler // Otherwise if PGOOD doesn't get asserted before 109f02daec1SMatt Spinler // the timer expires, it's a failure. 110f02daec1SMatt Spinler if (!pgoodPending()) 111f02daec1SMatt Spinler { 112f02daec1SMatt Spinler return EXIT_SUCCESS; 113f02daec1SMatt Spinler } 114f02daec1SMatt Spinler 1151a0c9176SWilliam A. Kennington III return timer.get_event().loop(); 116f02daec1SMatt Spinler } 117f02daec1SMatt Spinler catch (std::exception& e) 118f02daec1SMatt Spinler { 119f02daec1SMatt Spinler log<level::ERR>(e.what()); 120f02daec1SMatt Spinler log<level::ERR>("Unexpected failure prevented PGOOD checking"); 121f02daec1SMatt Spinler } 122f02daec1SMatt Spinler 123f02daec1SMatt Spinler // Letting the service fail won't help anything, so don't do it. 124f02daec1SMatt Spinler return EXIT_SUCCESS; 125f02daec1SMatt Spinler } 126f02daec1SMatt Spinler 127f0f02b9aSMatt Spinler } // namespace power 128f0f02b9aSMatt Spinler } // namespace witherspoon 129