diff options
author | Eddie James <eajames@us.ibm.com> | 2018-05-02 15:57:23 -0500 |
---|---|---|
committer | Edward A. James <eajames@us.ibm.com> | 2018-05-09 15:12:28 +0000 |
commit | b5508d7a0fd9202c37cc02aea045f189e991dd09 (patch) | |
tree | f592a56e0f5347aaf3fe77d54037988a4bf50570 | |
parent | 85e6520e0c431498e57b10a68b38f3cc4b1d8d88 (diff) | |
download | openpower-occ-control-b5508d7a0fd9202c37cc02aea045f189e991dd09.tar.gz openpower-occ-control-b5508d7a0fd9202c37cc02aea045f189e991dd09.zip |
Add Bus class to reset OCC bus driver
For some systems, the OCC is accessed over the SBEFIFO, acting as a bus.
If the SBE experiences a failure, the SBEFIFO driver is unable to
recover. Therefore, the OCC control application must force a reset of
the SBEFIFO driver when the OCC goes active.
Add a Bus class and reset method to unbind and bind the appropriate
SBEFIFO devices when the OCC devices are bound.
Testing: Powered on the system successfully. Injected SBE error through
a putscom. Without this fix, I intermittently saw SBEFIFO errors on the
BMC after the injection. With the fix, I saw no errors despite ~20
iterations.
Resolves openbmc/openbmc#3156
Change-Id: I0f9a230c57d0a3a7b59a874f62cdb1d93c6dcdfb
Signed-off-by: Eddie James <eajames@us.ibm.com>
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | configure.ac | 3 | ||||
-rw-r--r-- | occ_bus.cpp | 21 | ||||
-rw-r--r-- | occ_bus.hpp | 56 | ||||
-rw-r--r-- | occ_device.hpp | 41 | ||||
-rw-r--r-- | occ_status.hpp | 1 |
6 files changed, 109 insertions, 15 deletions
diff --git a/Makefile.am b/Makefile.am index b883f94..fddf9e7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4,6 +4,7 @@ noinst_HEADERS = \ occ_pass_through.hpp \ occ_status.hpp \ powercap.hpp \ + occ_bus.hpp \ occ_errors.hpp \ occ_events.hpp \ occ_finder.hpp \ @@ -21,6 +22,7 @@ libocc_control_la_SOURCES = \ occ_pass_through.cpp \ occ_manager.cpp \ occ_status.cpp \ + occ_bus.cpp \ occ_device.cpp \ occ_errors.cpp \ occ_presence.cpp \ diff --git a/configure.ac b/configure.ac index 149e0d0..7ac868c 100644 --- a/configure.ac +++ b/configure.ac @@ -105,6 +105,7 @@ AC_ARG_VAR(OCC_MASTER_NAME, [The OCC master object name]) AS_IF([test "x$OCC_MASTER_NAME" == "x"], [OCC_MASTER_NAME="occ-hwmon.1"]) AC_DEFINE_UNQUOTED([OCC_MASTER_NAME], ["$OCC_MASTER_NAME"], [The OCC master object name]) +AC_ARG_VAR(OCC_BUS_PATH, [The OCC bus device path]) AC_ARG_VAR(OCC_HWMON_PATH, [The OCC hwmon path]) AC_ARG_VAR(DEV_PATH, [The device path]) AC_ARG_VAR(I2C_OCC_DEVICE_NAME, [The device name of i2c occ hwmon]) @@ -115,9 +116,11 @@ AS_IF([test "x$enable_i2c_occ" == "xyes"], AS_IF([test "x$I2C_OCC_DEVICE_NAME" == "x"], [I2C_OCC_DEVICE_NAME="p8-occ-hwmon"]), # Else, define occ hwmon path for FSI + AS_IF([test "x$OCC_BUS_PATH" == "x"], [OCC_BUS_PATH="/sys/bus/fsi/drivers/sbefifo/"]) AS_IF([test "x$OCC_HWMON_PATH" == "x"], [OCC_HWMON_PATH="/sys/bus/platform/drivers/occ-hwmon/"]) AS_IF([test "x$DEV_PATH" == "x"], [DEV_PATH="/sys/bus/platform/devices/"]), ) +AC_DEFINE_UNQUOTED([OCC_BUS_PATH], ["$OCC_BUS_PATH"], [The OCC bus device path]) AC_DEFINE_UNQUOTED([OCC_HWMON_PATH], ["$OCC_HWMON_PATH"], [The OCC hwmon path]) AC_DEFINE_UNQUOTED([DEV_PATH], ["$DEV_PATH"], [The device path]) AC_DEFINE_UNQUOTED([I2C_OCC_DEVICE_NAME], ["$I2C_OCC_DEVICE_NAME"], [The device name of i2c occ hwmon]) diff --git a/occ_bus.cpp b/occ_bus.cpp new file mode 100644 index 0000000..27be21b --- /dev/null +++ b/occ_bus.cpp @@ -0,0 +1,21 @@ +#include "occ_device.hpp" +#include "occ_bus.hpp" + +namespace open_power +{ +namespace occ +{ + +fs::path Bus::bindPath = fs::path(OCC_BUS_PATH) / "bind"; +fs::path Bus::unBindPath = fs::path(OCC_BUS_PATH) / "unbind"; + +void Bus::reset() const +{ +#ifndef I2C_OCC + Device::write(unBindPath, config); + Device::write(bindPath, config); +#endif +} + +} // namespace occ +} // namespace open_power diff --git a/occ_bus.hpp b/occ_bus.hpp new file mode 100644 index 0000000..bdb4fa4 --- /dev/null +++ b/occ_bus.hpp @@ -0,0 +1,56 @@ +#pragma once + +#include <string> +#include <experimental/filesystem> + +namespace open_power +{ +namespace occ +{ + +namespace fs = std::experimental::filesystem; + +/** @class Bus + * @brief Manages the bus on which the OCC device exists + */ +class Bus +{ + public: + Bus() = delete; + ~Bus() = default; + Bus(const Bus&) = delete; + Bus& operator=(const Bus&) = delete; + Bus(Bus&&) = default; + Bus& operator=(Bus&&) = default; + + /** @brief Constructs the Bus object + * + * @param[in] instance - OCC device index + */ + explicit Bus(int instance) : + config("0" + std::to_string(instance) + ":0" + + std::to_string(instance) + ":00:06") + { + // Nothing to do here + } + + void reset() const; + + private: + /** @brief Config value to be used to do bind and unbind */ + const std::string config; + + /** @brief To bind the device to the OCC's bus driver, do: + * + * Write 0x:0x:00:06 to: /sys/bus/fsi/drivers/sbefifo/bind + */ + static fs::path bindPath; + + /** @brief To un-bind the dvice from the OCC's bus driver, do: + * Write 0x:0x:00:06 to: /sys/bus/fsi/drivers/sbefifo/unbind + */ + static fs::path unBindPath; +}; + +} // namespace occ +} // namespace open_power diff --git a/occ_device.hpp b/occ_device.hpp index efa46dc..85abde6 100644 --- a/occ_device.hpp +++ b/occ_device.hpp @@ -2,6 +2,7 @@ #include <fstream> #include <experimental/filesystem> +#include "occ_bus.hpp" #include "occ_events.hpp" #include "occ_errors.hpp" #include "occ_presence.hpp" @@ -34,16 +35,20 @@ class Device * @param[in] event - Unique ptr reference to sd_event * @param[in] name - OCC instance name * @param[in] manager - OCC manager instance + * @param[in] status - OCC status instance + * @param[in] instance - OCC device index * @param[in] callback - Optional callback on errors */ Device(EventPtr& event, const std::string& name, const Manager& manager, Status& status, + int instance, std::function<void(bool)> callBack = nullptr) : config(name), errorFile(fs::path(config) / "occ_error"), statusObject(status), + busObject(instance), error(event, errorFile, callBack), presence(event, fs::path(config) / "occs_present", @@ -74,6 +79,9 @@ class Device /** @brief Binds device to the OCC driver */ inline void bind() { + // Reset this OCC's bus driver + busObject.reset(); + // Bind the device return write(bindPath, config); } @@ -128,6 +136,21 @@ class Device } } + /** @brief file writer to achieve bind and unbind + * + * @param[in] filename - Name of file to be written + * @param[in] data - Data to be written to + * @return - None + */ + static void write(const fs::path& fileName, const std::string& data) + { + // If there is an error, move the exception all the way up + std::ofstream file(fileName, std::ios::out); + file << data; + file.close(); + return; + } + private: /** @brief Config value to be used to do bind and unbind */ const std::string config; @@ -149,6 +172,9 @@ class Device /** Store the associated Status instance */ Status& statusObject; + /** Store the associated Bus instance */ + const Bus busObject; + /** Abstraction of error monitoring */ Error error; @@ -160,21 +186,6 @@ class Device Error throttleProcPower; Error throttleMemTemp; - /** @brief file writer to achieve bind and unbind - * - * @param[in] filename - Name of file to be written - * @param[in] data - Data to be written to - * @return - None - */ - void write(const fs::path& fileName, const std::string& data) - { - // If there is an error, move the exception all the way up - std::ofstream file(fileName, std::ios::out); - file << data; - file.close(); - return; - } - /** @brief Returns if device represents the master OCC */ bool master() const; diff --git a/occ_status.hpp b/occ_status.hpp index f14bd7d..579f29d 100644 --- a/occ_status.hpp +++ b/occ_status.hpp @@ -74,6 +74,7 @@ class Status : public Interface #endif manager, *this, + instance, std::bind(std::mem_fn(&Status::deviceErrorHandler), this, std::placeholders::_1)), hostControlSignal( |