/** * Copyright (C) 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 #include #include #include #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("Failed to run the FSI master scan"); using metadata = org::open_power::Proc::FSI::MasterDetectionFailure; elog( metadata::CALLOUT_ERRNO(e.code().value()), metadata::CALLOUT_DEVICE_PATH(masterCalloutPath)); } if (!fs::exists(hubScanPath)) { log("The FSI master scan did not create a hub scan file"); using metadata = org::open_power::Proc::FSI::MasterDetectionFailure; elog( 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("Failed to run the FSI hub scan"); using metadata = org::open_power::Proc::FSI::SlaveDetectionFailure; elog( metadata::ERRNO(e.code().value())); } } REGISTER_PROCEDURE("scanFSI", scan); } }