xref: /openbmc/openpower-occ-control/occ_device.hpp (revision f0295f52536d9e508305a0e522184157966ee2f5)
1 #pragma once
2 
3 #include "config.h"
4 
5 #include "occ_errors.hpp"
6 #include "occ_events.hpp"
7 #include "occ_ffdc.hpp"
8 #include "occ_presence.hpp"
9 #include "powermode.hpp"
10 
11 #include <org/open_power/OCC/Device/error.hpp>
12 
13 #include <filesystem>
14 #include <fstream>
15 #include <regex>
16 
17 namespace open_power
18 {
19 namespace occ
20 {
21 
22 class Manager;
23 class Status;
24 namespace fs = std::filesystem;
25 using namespace sdbusplus::org::open_power::OCC::Device::Error;
26 
27 /** @class Device
28  *  @brief Binds and unbinds the OCC driver upon request
29  */
30 class Device
31 {
32   public:
33     Device() = delete;
34     ~Device() = default;
35     Device(const Device&) = delete;
36     Device& operator=(const Device&) = delete;
37     Device(Device&&) = default;
38     Device& operator=(Device&&) = default;
39 
40     /** @brief Constructs the Device object
41      *
42      *  @param[in] event    - Unique ptr reference to sd_event
43      *  @param[in] path     - Path to the OCC instance
44      *  @param[in] manager  - OCC manager instance
45      *  @param[in] status   - Status instance
46      *  @param[in] instance - OCC instance number
47      */
Device(EventPtr & event,const fs::path & path,Manager & manager,Status & status,std::unique_ptr<powermode::PowerMode> & powerModeRef,unsigned int instance=0)48     Device(EventPtr& event, const fs::path& path, Manager& manager,
49            Status& status,
50 #ifdef POWER10
51            std::unique_ptr<powermode::PowerMode>& powerModeRef,
52 #endif
53            unsigned int instance = 0) :
54         devPath(path), instance(instance), statusObject(status),
55         managerObject(manager),
56         error(event, path / "occ_error",
57               std::bind(std::mem_fn(&Device::errorCallback), this,
58                         std::placeholders::_1)),
59         timeout(event,
60                 path /
61                     fs::path("../../sbefifo" + std::to_string(instance + 1)) /
62                     "timeout",
63 #ifdef PLDM
64                 std::bind(std::mem_fn(&Device::timeoutCallback), this,
65                           std::placeholders::_1)
66 #else
67                 nullptr
68 #endif
69                     ),
70         ffdc(event, path / "ffdc", instance),
71         presence(event, path / "occs_present", manager,
72                  std::bind(std::mem_fn(&Device::errorCallback), this,
73                            std::placeholders::_1)),
74         throttleProcTemp(
75             event, path / "occ_dvfs_overtemp",
76             std::bind(std::mem_fn(&Device::throttleProcTempCallback), this,
77                       std::placeholders::_1)),
78         throttleProcPower(
79             event, path / "occ_dvfs_power",
80             std::bind(std::mem_fn(&Device::throttleProcPowerCallback), this,
81                       std::placeholders::_1)),
82         throttleMemTemp(event, path / "occ_mem_throttle",
83                         std::bind(std::mem_fn(&Device::throttleMemTempCallback),
84                                   this, std::placeholders::_1))
85 #ifdef POWER10
86         ,
87         pmode(powerModeRef)
88 #endif
89     {
90         // Nothing to do here
91     }
92 
93     /** @brief Sets the device active or inactive
94      *
95      * @param[in] active - Indicates whether or not to set the device active
96      */
97     void setActive(bool active);
98 
99     /** @brief Starts to monitor for errors
100      *
101      *  @param[in] poll - Indicates whether or not the error file should
102      *                    actually be polled for changes. Disabling polling is
103      *                    necessary for error files that don't support the poll
104      *                    file operation.
105      */
addErrorWatch(bool poll=true)106     inline void addErrorWatch(bool poll = true)
107     {
108 #ifdef POWER10
109         throttleProcTemp.addWatch(poll);
110 #else
111         try
112         {
113             throttleProcTemp.addWatch(poll);
114         }
115         catch (const OpenFailure& e)
116         {
117             // try the old kernel version
118             throttleProcTemp.setFile(devPath / "occ_dvfs_ot");
119             throttleProcTemp.addWatch(poll);
120         }
121 #endif
122 
123 #ifdef POWER10
124         if (master())
125         {
126             pmode->addIpsWatch(poll);
127         }
128 #endif
129 
130         throttleProcPower.addWatch(poll);
131         throttleMemTemp.addWatch(poll);
132 
133         try
134         {
135             ffdc.addWatch(poll);
136         }
137         catch (const OpenFailure& e)
138         {
139             // nothing to do if there is no FFDC file
140         }
141 
142         try
143         {
144             timeout.addWatch(poll);
145         }
146         catch (const std::exception& e)
147         {
148             // nothing to do if there is no SBE timeout file
149         }
150 
151         error.addWatch(poll);
152     }
153 
154     /** @brief stops monitoring for errors */
removeErrorWatch()155     inline void removeErrorWatch()
156     {
157         // we can always safely remove watch even if we don't add it
158         presence.removeWatch();
159         ffdc.removeWatch();
160         error.removeWatch();
161         timeout.removeWatch();
162         throttleMemTemp.removeWatch();
163         throttleProcPower.removeWatch();
164         throttleProcTemp.removeWatch();
165 #ifdef POWER10
166         if (master())
167         {
168             pmode->removeIpsWatch();
169         }
170 #endif
171     }
172 
173     /** @brief Starts to watch how many OCCs are present on the master */
addPresenceWatchMaster()174     inline void addPresenceWatchMaster()
175     {
176         if (master())
177         {
178             presence.addWatch();
179         }
180     }
181 
182     /** @brief helper function to get the last part of the path
183      *
184      * @param[in] path - Path to parse
185      * @return         - Last directory name in the path
186      */
187     static std::string getPathBack(const fs::path& path);
188 
189     /** @brief Returns true if the device is active */
190     bool active() const;
191 
192     /** @brief Returns true if device represents the master OCC */
193     bool master() const;
194 
195   private:
196     /** @brief This directory contains the error files */
197     const fs::path devPath;
198 
199     /** @brief OCC instance ID */
200     const unsigned int instance;
201 
202     /**  Store the associated Status instance */
203     Status& statusObject;
204 
205     /** Store the parent Manager instance */
206     Manager& managerObject;
207 
208     /** Abstraction of error monitoring */
209     Error error;
210 
211     /** Abstraction of SBE timeout monitoring */
212     Error timeout;
213 
214     /** SBE FFDC monitoring */
215     FFDC ffdc;
216 
217     /** Abstraction of OCC presence monitoring */
218     Presence presence;
219 
220     /** Error instances for watching for throttling events */
221     Error throttleProcTemp;
222     Error throttleProcPower;
223     Error throttleMemTemp;
224 
225 #ifdef POWER10
226     /** @brief OCC PowerMode object */
227     std::unique_ptr<powermode::PowerMode>& pmode;
228 #endif
229 
230     /** @brief file reader to read a binary string ("1" or "0")
231      *
232      * @param[in] fileName - Name of file to be read
233      * @return             - The value returned by reading the file
234      */
235     bool readBinary(const std::string& fileName) const;
236 
237     /** @brief file writer to achieve bind and unbind
238      *
239      *  @param[in] filename - Name of file to be written
240      *  @param[in] data     - Data to be written to
241      *  @return             - None
242      */
write(const fs::path & fileName,const std::string & data)243     void write(const fs::path& fileName, const std::string& data)
244     {
245         // If there is an error, move the exception all the way up
246         std::ofstream file(fileName, std::ios::out);
247         file << data;
248         file.close();
249         return;
250     }
251 
252     /** @brief callback for OCC error monitoring
253      *
254      * @param[in] error - Errno stored in the error file, 0 if no error
255      */
256     void errorCallback(int error);
257 
258     /** @brief callback for OCC presence monitoring
259      *
260      * @param[in] occsPresent - The number of OCCs indicated in the poll
261      * response
262      */
263     void presenceCallback(int occsPresent);
264 
265 #ifdef PLDM
266     /** @brief callback for SBE timeout monitoring
267      *
268      * @param[in] error - True if an error is reported, false otherwise
269      */
270     void timeoutCallback(int error);
271 #endif
272 
273     /** @brief callback for the proc temp throttle event
274      *
275      *  @param[in] error - True if an error is reported, false otherwise
276      */
277     void throttleProcTempCallback(int error);
278 
279     /** @brief callback for the proc power throttle event
280      *
281      *  @param[in] error - True if an error is reported, false otherwise
282      */
283     void throttleProcPowerCallback(int error);
284 
285     /** @brief callback for the proc temp throttle event
286      *
287      *  @param[in] error - True if an error is reported, false otherwise
288      */
289     void throttleMemTempCallback(int error);
290 
291     /** @brief Get the pathname for a file based on a regular expression
292      *
293      *  @param[in] basePath - The path where the files will be checked
294      *  @param[in] expr - Regular expression describing the target file
295      *
296      *  @return path to the file or empty path if not found
297      */
298     fs::path getFilenameByRegex(fs::path basePath,
299                                 const std::regex& expr) const;
300 };
301 
302 } // namespace occ
303 } // namespace open_power
304