From ee4d83dfc7b6cf3b5979541ab5b1918b68e6bbdb Mon Sep 17 00:00:00 2001 From: Vishwanatha Subbanna Date: Thu, 29 Jun 2017 18:35:00 +0530 Subject: Add support to watch for OCC errors Change-Id: I98d95020a2d01e281e5c8efa825d6b4bd4c6c160 Signed-off-by: Vishwanatha Subbanna --- occ_errors.cpp | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 occ_errors.cpp (limited to 'occ_errors.cpp') diff --git a/occ_errors.cpp b/occ_errors.cpp new file mode 100644 index 0000000..f2da49f --- /dev/null +++ b/occ_errors.cpp @@ -0,0 +1,145 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "occ_errors.hpp" +#include "elog-errors.hpp" +namespace open_power +{ +namespace occ +{ + +// Value in error file indicating success +constexpr auto NO_ERROR = '0'; + +using namespace phosphor::logging; +using namespace sdbusplus::org::open_power::OCC::Device::Error; +using InternalFailure = sdbusplus::xyz::openbmc_project::Common:: + Error::InternalFailure; + +// Populate the file descriptor on the error file +void Error::openFile() +{ + using namespace phosphor::logging; + + fd = open(file.c_str(), O_RDONLY | O_NONBLOCK); + if (fd < 0) + { + elog( + phosphor::logging::org::open_power::OCC::Device:: + OpenFailure::CALLOUT_ERRNO(errno), + phosphor::logging::org::open_power::OCC::Device:: + OpenFailure::CALLOUT_DEVICE_PATH(file.c_str())); + } +} + +// Attaches the FD to event loop and registers the callback handler +void Error::registerCallBack() +{ + decltype(eventSource.get()) sourcePtr = nullptr; + auto r = sd_event_add_io(event.get(), &sourcePtr, fd, + EPOLLIN, processEvents, this); + eventSource.reset(sourcePtr); + + if (r < 0) + { + log("Failed to register callback handler", + entry("ERROR=%s", strerror(-r))); + elog(); + } +} + +// Starts to watch for errors +void Error::addWatch() +{ + // Open the file + openFile(); + + // register the callback handler + registerCallBack(); +} + +// Stops watching for errors +void Error::removeWatch() +{ + // Close the file + if (fd >= 0) + { + close(fd); + } + + // Reduce the reference count. Since there is only one instances + // of add_io, this will result empty loop + eventSource.reset(); +} + +// Callback handler when there is an activity on the FD +int Error::processEvents(sd_event_source* es, int fd, + uint32_t revents, void* userData) +{ + log("Error file updated"); + auto error = static_cast(userData); + + error->analyzeEvent(); + return 0; +} + +// Reads the error file and analyzes the data +void Error::analyzeEvent() +{ + // Get the number of bytes to read + int len = -1; + auto r = ioctl(fd, FIONREAD, &len); + if (r < 0) + { + elog( + phosphor::logging::org::open_power::OCC::Device:: + ConfigFailure::CALLOUT_ERRNO(errno), + phosphor::logging::org::open_power::OCC::Device:: + ConfigFailure::CALLOUT_DEVICE_PATH(file.c_str())); + } + + // A non-zero data indicates an error condition + // Let the caller take appropriate action on this + auto data = readFile(len); + if (data.empty() || + data.front() == NO_ERROR) + { + return; + } + + // This must be an error + if (callBack) + { + callBack(); + } + return; +} + +// Reads so many bytes as passed in +std::string Error::readFile(int len) const +{ + auto data = std::make_unique(len+1); + + // This file get created soon after binding. A value of 0 is + // deemed success and anything else is a Failure + // Since all the sysfs files would have size of 4096, if we read 0 + // bytes -or- value '0', then it just means we are fine + auto r = read(fd, data.get(), len); + if (r < 0) + { + elog( + phosphor::logging::org::open_power::OCC::Device:: + ReadFailure::CALLOUT_ERRNO(errno), + phosphor::logging::org::open_power::OCC::Device:: + ReadFailure::CALLOUT_DEVICE_PATH(file.c_str())); + } + return std::string(data.get()); +} + +} // namespace occ +} // namespace open_power -- cgit v1.2.1