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