diff options
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | configure.ac | 6 | ||||
-rw-r--r-- | proc_control.cpp | 13 | ||||
-rw-r--r-- | procedures/openfsi/scan.cpp | 133 |
4 files changed, 152 insertions, 2 deletions
diff --git a/Makefile.am b/Makefile.am index e76cfba..54dc22e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -16,11 +16,13 @@ CLEANFILES = openpower_procedures.cpp openpower_proc_control_LDFLAGS = $(PHOSPHOR_LOGGING_LIBS) \ $(PHOSPHOR_DBUS_INTERFACES_LIBS) \ + $(OPENPOWER_DBUS_INTERFACES_LIBS) \ $(SDBUSPLUS_LIBS) \ -lstdc++fs openpower_proc_control_CXXFLAGS = $(PHOSPHOR_LOGGING_CFLAGS) \ $(PHOSPHOR_DBUS_INTERFACES_CFLAGS) \ + $(OPENPOWER_DBUS_INTERFACES_CFLAGS) \ $(SDBUSPLUS_CFLAGS) SUBDIRS = test diff --git a/configure.ac b/configure.ac index cc2d823..e0534a9 100644 --- a/configure.ac +++ b/configure.ac @@ -37,9 +37,9 @@ AS_IF([test "x$enable_oe_sdk" == "xyes"], AC_SUBST([OESDK_TESTCASE_FLAGS], [$testcase_flags]) ) -#CHIPS can be passed in a from a recipe, or it will default to P9 +#CHIPS can be passed in a from a recipe, or it will default to P9 and openfsi AC_ARG_VAR(CHIPS, [The list of chips to build the procedures for]) -AS_IF([test "x$CHIPS" == "x"], [CHIPS="p9"]) +AS_IF([test "x$CHIPS" == "x"], [CHIPS="p9 openfsi"]) AC_CONFIG_FILES([Makefile.generated], [${srcdir}/gen_makefile.sh ${srcdir} "$myChips" > Makefile.generated], @@ -47,5 +47,7 @@ AC_CONFIG_FILES([Makefile.generated], PKG_CHECK_MODULES([PHOSPHOR_LOGGING], [phosphor-logging],, [AC_MSG_ERROR([Could not find phosphor-logging...openbmc/phosphor-logging package required])]) PKG_CHECK_MODULES([PHOSPHOR_DBUS_INTERFACES], [phosphor-dbus-interfaces], [], [AC_MSG_ERROR(["phosphor-dbus-interfaces required and not found."])]) +PKG_CHECK_MODULES([OPENPOWER_DBUS_INTERFACES], [openpower-dbus-interfaces], [], [AC_MSG_ERROR(["openpower-dbus-interfaces required and not found."])]) + AC_CONFIG_FILES([Makefile test/Makefile]) AC_OUTPUT diff --git a/proc_control.cpp b/proc_control.cpp index f825510..7de54df 100644 --- a/proc_control.cpp +++ b/proc_control.cpp @@ -19,6 +19,7 @@ #include <phosphor-logging/log.hpp> #include <phosphor-logging/elog.hpp> #include <phosphor-logging/elog-errors.hpp> +#include <org/open_power/Proc/FSI/error.hpp> #include <xyz/openbmc_project/Common/error.hpp> #include <xyz/openbmc_project/Common/Device/error.hpp> #include <xyz/openbmc_project/Common/File/error.hpp> @@ -31,6 +32,7 @@ namespace device_error = sdbusplus::xyz::openbmc_project:: Common::Device::Error; namespace file_error = sdbusplus::xyz::openbmc_project:: Common::File::Error; +namespace fsi_error = sdbusplus::org::open_power::Proc::FSI::Error; void usage(char** argv, const ProcedureMap& procedures) { @@ -93,6 +95,17 @@ int main(int argc, char** argv) commit<common_error::InvalidArgument>(); return -1; } + catch (fsi_error::MasterDetectionFailure& e) + { + commit<fsi_error::MasterDetectionFailure>(); + return -1; + } + catch (fsi_error::SlaveDetectionFailure& e) + { + commit<fsi_error::SlaveDetectionFailure>(); + return -1; + } + return 0; } diff --git a/procedures/openfsi/scan.cpp b/procedures/openfsi/scan.cpp new file mode 100644 index 0000000..273d280 --- /dev/null +++ b/procedures/openfsi/scan.cpp @@ -0,0 +1,133 @@ + +/** + * Copyright © 2017 IBM Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include <experimental/filesystem> +#include <fstream> +#include <org/open_power/Proc/FSI/error.hpp> +#include <phosphor-logging/log.hpp> +#include "registration.hpp" + +namespace openpower +{ +namespace openfsi +{ + +using namespace phosphor::logging; +namespace fs = std::experimental::filesystem; +namespace fsi_error = sdbusplus::org::open_power::Proc::FSI::Error; + +constexpr auto masterScanPath = + "/sys/bus/platform/devices/gpio-fsi/fsi0/rescan"; + +constexpr auto hubScanPath = + "/sys/devices/platform/gpio-fsi/fsi0/slave@00:00/" + "00:00:00:0a/fsi1/rescan"; + +constexpr auto masterCalloutPath = + "/sys/devices/platform/gpio-fsi/fsi0/slave@00:00/raw"; + + +/** + * Writes a 1 to the sysfs file passed in to trigger + * the device driver to do an FSI scan. + * + * @param[in] path - the sysfs path to write a 1 to + */ +static void doScan(const std::string& path) +{ + std::ofstream file; + + file.exceptions(std::ofstream::failbit | //logic error on operation + std::ofstream::badbit | //read/write error on operation + std::ofstream::eofbit); //end of file reached + try + { + file.open(path); + file << "1"; + } + catch (std::exception& e) + { + auto err = errno; + throw std::system_error(err, std::generic_category()); + } +} + +/** + * Performs an FSI master scan followed by an FSI hub scan. + * This is where the device driver detects which chips are present. + * + * This is unrelated to scanning a ring out of a chip. + */ +void scan() +{ + //Note: Currently the FSI device driver will always return success on both + //the master and hub scans. The only way we can detect something + //went wrong is if the master scan didn't create the hub scan file, so + //we will check for that. + //It is possible the driver will be updated in the future to actually + //return a failure so the code will still check for them. + + try + { + doScan(masterScanPath); + } + catch (std::system_error& e) + { + log<level::ERR>("Failed to run the FSI master scan"); + + using metadata = org::open_power::Proc::FSI::MasterDetectionFailure; + + elog<fsi_error::MasterDetectionFailure>( + metadata::CALLOUT_ERRNO(e.code().value()), + metadata::CALLOUT_DEVICE_PATH(masterCalloutPath)); + } + + if (!fs::exists(hubScanPath)) + { + log<level::ERR>("The FSI master scan did not create a hub scan file"); + + using metadata = org::open_power::Proc::FSI::MasterDetectionFailure; + + elog<fsi_error::MasterDetectionFailure>( + metadata::CALLOUT_ERRNO(0), + metadata::CALLOUT_DEVICE_PATH(masterCalloutPath)); + } + + try + { + doScan(hubScanPath); + } + catch (std::system_error& e) + { + //If the device driver is ever updated in the future to fail the sysfs + //write call on a scan failure then it should also provide some hints + //about which hardware failed so we can do an appropriate callout + //here. At this point in time, the driver shouldn't ever fail so + //we won't worry about guessing at the callout. + + log<level::ERR>("Failed to run the FSI hub scan"); + + using metadata = org::open_power::Proc::FSI::SlaveDetectionFailure; + + elog<fsi_error::SlaveDetectionFailure>( + metadata::ERRNO(e.code().value())); + } +} + +REGISTER_PROCEDURE("scanFSI", scan); + +} +} |