diff options
author | Vishwanatha Subbanna <vishwa@linux.vnet.ibm.com> | 2017-06-29 18:35:00 +0530 |
---|---|---|
committer | Vishwanatha Subbanna <vishwa@linux.vnet.ibm.com> | 2017-07-29 23:57:59 +0530 |
commit | ee4d83dfc7b6cf3b5979541ab5b1918b68e6bbdb (patch) | |
tree | 4d186ddf133d77880e857fccdddb71fcc155a6bf /occ_errors.cpp | |
parent | 554d60059e7d0b699b3cdcbe8de2c341613e9931 (diff) | |
download | openpower-occ-control-ee4d83dfc7b6cf3b5979541ab5b1918b68e6bbdb.tar.gz openpower-occ-control-ee4d83dfc7b6cf3b5979541ab5b1918b68e6bbdb.zip |
Add support to watch for OCC errors
Change-Id: I98d95020a2d01e281e5c8efa825d6b4bd4c6c160
Signed-off-by: Vishwanatha Subbanna <vishwa@linux.vnet.ibm.com>
Diffstat (limited to 'occ_errors.cpp')
-rw-r--r-- | occ_errors.cpp | 145 |
1 files changed, 145 insertions, 0 deletions
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 <fcntl.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <errno.h> +#include <phosphor-logging/log.hpp> +#include <phosphor-logging/elog.hpp> +#include <xyz/openbmc_project/Common/error.hpp> +#include <org/open_power/OCC/Device/error.hpp> +#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<OpenFailure>( + 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<level::ERR>("Failed to register callback handler", + entry("ERROR=%s", strerror(-r))); + elog<InternalFailure>(); + } +} + +// 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<level::INFO>("Error file updated"); + auto error = static_cast<Error*>(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<ConfigFailure>( + 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<char[]>(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<ReadFailure>( + 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 |