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 51 std::unique_ptr<powermode::PowerMode>& powerModeRef, 52 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 std::bind(std::mem_fn(&Device::timeoutCallback), this, 64 std::placeholders::_1)), 65 ffdc(event, path / "ffdc", instance), 66 presence(event, path / "occs_present", manager, 67 std::bind(std::mem_fn(&Device::errorCallback), this, 68 std::placeholders::_1)), 69 throttleProcTemp( 70 event, path / "occ_dvfs_overtemp", 71 std::bind(std::mem_fn(&Device::throttleProcTempCallback), this, 72 std::placeholders::_1)), 73 throttleProcPower( 74 event, path / "occ_dvfs_power", 75 std::bind(std::mem_fn(&Device::throttleProcPowerCallback), this, 76 std::placeholders::_1)), 77 throttleMemTemp(event, path / "occ_mem_throttle", 78 std::bind(std::mem_fn(&Device::throttleMemTempCallback), 79 this, std::placeholders::_1)), 80 pmode(powerModeRef) 81 { 82 // Nothing to do here 83 } 84 85 /** @brief Sets the device active or inactive 86 * 87 * @param[in] active - Indicates whether or not to set the device active 88 */ 89 void setActive(bool active); 90 91 /** @brief Starts to monitor for errors 92 * 93 * @param[in] poll - Indicates whether or not the error file should 94 * actually be polled for changes. Disabling polling is 95 * necessary for error files that don't support the poll 96 * file operation. 97 */ addErrorWatch(bool poll=true)98 inline void addErrorWatch(bool poll = true) 99 { 100 throttleProcTemp.addWatch(poll); 101 102 if (master()) 103 { 104 pmode->addIpsWatch(poll); 105 } 106 107 throttleProcPower.addWatch(poll); 108 throttleMemTemp.addWatch(poll); 109 110 try 111 { 112 ffdc.addWatch(poll); 113 } 114 catch (const OpenFailure& e) 115 { 116 // nothing to do if there is no FFDC file 117 } 118 119 try 120 { 121 timeout.addWatch(poll); 122 } 123 catch (const std::exception& e) 124 { 125 // nothing to do if there is no SBE timeout file 126 } 127 128 error.addWatch(poll); 129 } 130 131 /** @brief stops monitoring for errors */ removeErrorWatch()132 inline void removeErrorWatch() 133 { 134 // we can always safely remove watch even if we don't add it 135 presence.removeWatch(); 136 ffdc.removeWatch(); 137 error.removeWatch(); 138 timeout.removeWatch(); 139 throttleMemTemp.removeWatch(); 140 throttleProcPower.removeWatch(); 141 throttleProcTemp.removeWatch(); 142 143 if (master()) 144 { 145 pmode->removeIpsWatch(); 146 } 147 } 148 149 /** @brief Starts to watch how many OCCs are present on the master */ addPresenceWatchMaster()150 inline void addPresenceWatchMaster() 151 { 152 if (master()) 153 { 154 presence.addWatch(); 155 } 156 } 157 158 /** @brief helper function to get the last part of the path 159 * 160 * @param[in] path - Path to parse 161 * @return - Last directory name in the path 162 */ 163 static std::string getPathBack(const fs::path& path); 164 165 /** @brief Returns true if the device is active */ 166 bool active() const; 167 168 /** @brief Returns true if device represents the master OCC */ 169 bool master() const; 170 171 private: 172 /** @brief This directory contains the error files */ 173 const fs::path devPath; 174 175 /** @brief OCC instance ID */ 176 const unsigned int instance; 177 178 /** Store the associated Status instance */ 179 Status& statusObject; 180 181 /** Store the parent Manager instance */ 182 Manager& managerObject; 183 184 /** Abstraction of error monitoring */ 185 Error error; 186 187 /** Abstraction of SBE timeout monitoring */ 188 Error timeout; 189 190 /** SBE FFDC monitoring */ 191 FFDC ffdc; 192 193 /** Abstraction of OCC presence monitoring */ 194 Presence presence; 195 196 /** Error instances for watching for throttling events */ 197 Error throttleProcTemp; 198 Error throttleProcPower; 199 Error throttleMemTemp; 200 201 /** @brief OCC PowerMode object */ 202 std::unique_ptr<powermode::PowerMode>& pmode; 203 204 /** @brief file reader to read a binary string ("1" or "0") 205 * 206 * @param[in] fileName - Name of file to be read 207 * @return - The value returned by reading the file 208 */ 209 bool readBinary(const std::string& fileName) const; 210 211 /** @brief file writer to achieve bind and unbind 212 * 213 * @param[in] filename - Name of file to be written 214 * @param[in] data - Data to be written to 215 * @return - None 216 */ write(const fs::path & fileName,const std::string & data)217 void write(const fs::path& fileName, const std::string& data) 218 { 219 // If there is an error, move the exception all the way up 220 std::ofstream file(fileName, std::ios::out); 221 file << data; 222 file.close(); 223 return; 224 } 225 226 /** @brief callback for OCC error monitoring 227 * 228 * @param[in] error - Errno stored in the error file, 0 if no error 229 */ 230 void errorCallback(int error); 231 232 /** @brief callback for OCC presence monitoring 233 * 234 * @param[in] occsPresent - The number of OCCs indicated in the poll 235 * response 236 */ 237 void presenceCallback(int occsPresent); 238 239 /** @brief callback for SBE timeout monitoring 240 * 241 * @param[in] error - True if an error is reported, false otherwise 242 */ 243 void timeoutCallback(int error); 244 245 /** @brief callback for the proc temp throttle event 246 * 247 * @param[in] error - True if an error is reported, false otherwise 248 */ 249 void throttleProcTempCallback(int error); 250 251 /** @brief callback for the proc power throttle event 252 * 253 * @param[in] error - True if an error is reported, false otherwise 254 */ 255 void throttleProcPowerCallback(int error); 256 257 /** @brief callback for the proc temp throttle event 258 * 259 * @param[in] error - True if an error is reported, false otherwise 260 */ 261 void throttleMemTempCallback(int error); 262 263 /** @brief Get the pathname for a file based on a regular expression 264 * 265 * @param[in] basePath - The path where the files will be checked 266 * @param[in] expr - Regular expression describing the target file 267 * 268 * @return path to the file or empty path if not found 269 */ 270 fs::path getFilenameByRegex(fs::path basePath, 271 const std::regex& expr) const; 272 }; 273 274 } // namespace occ 275 } // namespace open_power 276