1 /** 2 * Copyright (C) 2017 IBM Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #include "registration.hpp" 17 18 #include <org/open_power/Proc/FSI/error.hpp> 19 #include <phosphor-logging/elog-errors.hpp> 20 #include <phosphor-logging/log.hpp> 21 22 #include <filesystem> 23 #include <fstream> 24 25 namespace openpower 26 { 27 namespace openfsi 28 { 29 30 using namespace phosphor::logging; 31 namespace fsi_error = sdbusplus::org::open_power::Proc::FSI::Error; 32 33 constexpr auto masterScanPath = "/sys/class/fsi-master/fsi0/rescan"; 34 constexpr auto hubScanPath = "/sys/class/fsi-master/fsi1/rescan"; 35 constexpr auto masterCalloutPath = "/sys/class/fsi-master/fsi0/slave@00:00/raw"; 36 37 /** 38 * Writes a 1 to the sysfs file passed in to trigger 39 * the device driver to do an FSI scan. 40 * 41 * @param[in] path - the sysfs path to write a 1 to 42 */ 43 static void doScan(const std::string& path) 44 { 45 std::ofstream file; 46 47 file.exceptions(std::ofstream::failbit | // logic error on operation 48 std::ofstream::badbit | // read/write error on operation 49 std::ofstream::eofbit); // end of file reached 50 try 51 { 52 file.open(path); 53 file << "1"; 54 } 55 catch (const std::exception& e) 56 { 57 auto err = errno; 58 throw std::system_error(err, std::generic_category()); 59 } 60 } 61 62 /** 63 * Performs an FSI master scan followed by an FSI hub scan. 64 * This is where the device driver detects which chips are present. 65 * 66 * This is unrelated to scanning a ring out of a chip. 67 */ 68 void scan() 69 { 70 // Note: Currently the FSI device driver will always return success on both 71 // the master and hub scans. The only way we can detect something 72 // went wrong is if the master scan didn't create the hub scan file, so 73 // we will check for that. 74 // It is possible the driver will be updated in the future to actually 75 // return a failure so the code will still check for them. 76 77 try 78 { 79 doScan(masterScanPath); 80 } 81 catch (const std::system_error& e) 82 { 83 log<level::ERR>("Failed to run the FSI master scan"); 84 85 using metadata = org::open_power::Proc::FSI::MasterDetectionFailure; 86 87 elog<fsi_error::MasterDetectionFailure>( 88 metadata::CALLOUT_ERRNO(e.code().value()), 89 metadata::CALLOUT_DEVICE_PATH(masterCalloutPath)); 90 } 91 92 if (!std::filesystem::exists(hubScanPath)) 93 { 94 log<level::ERR>("The FSI master scan did not create a hub scan file"); 95 96 using metadata = org::open_power::Proc::FSI::MasterDetectionFailure; 97 98 elog<fsi_error::MasterDetectionFailure>( 99 metadata::CALLOUT_ERRNO(0), 100 metadata::CALLOUT_DEVICE_PATH(masterCalloutPath)); 101 } 102 103 try 104 { 105 doScan(hubScanPath); 106 } 107 catch (const std::system_error& e) 108 { 109 // If the device driver is ever updated in the future to fail the sysfs 110 // write call on a scan failure then it should also provide some hints 111 // about which hardware failed so we can do an appropriate callout 112 // here. At this point in time, the driver shouldn't ever fail so 113 // we won't worry about guessing at the callout. 114 115 log<level::ERR>("Failed to run the FSI hub scan"); 116 117 using metadata = org::open_power::Proc::FSI::SlaveDetectionFailure; 118 119 elog<fsi_error::SlaveDetectionFailure>( 120 metadata::ERRNO(e.code().value())); 121 } 122 } 123 124 REGISTER_PROCEDURE("scanFSI", scan) 125 126 } // namespace openfsi 127 } // namespace openpower 128