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