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