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