xref: /openbmc/openpower-proc-control/procedures/openfsi/scan.cpp (revision 56d14d049bcb1966fac953d1bf07a9e5bedf5ebc)
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