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 10 #include <org/open_power/OCC/Device/error.hpp> 11 12 #include <filesystem> 13 #include <fstream> 14 15 namespace open_power 16 { 17 namespace occ 18 { 19 20 class Manager; 21 class Status; 22 namespace fs = std::filesystem; 23 using namespace sdbusplus::org::open_power::OCC::Device::Error; 24 25 /** @class Device 26 * @brief Binds and unbinds the OCC driver upon request 27 */ 28 class Device 29 { 30 public: 31 Device() = delete; 32 ~Device() = default; 33 Device(const Device&) = delete; 34 Device& operator=(const Device&) = delete; 35 Device(Device&&) = default; 36 Device& operator=(Device&&) = default; 37 38 /** @brief Constructs the Device object 39 * 40 * @param[in] event - Unique ptr reference to sd_event 41 * @param[in] path - Path to the OCC instance 42 * @param[in] manager - OCC manager instance 43 * @param[in] status - Status instance 44 * @param[in] instance - OCC instance number 45 * @param[in] callback - Optional callback on errors 46 */ 47 Device(EventPtr& event, const fs::path& path, const Manager& manager, 48 Status& status, unsigned int instance = 0, 49 std::function<void(bool)> callBack = nullptr) : 50 config(getPathBack(path)), 51 devPath(path), statusObject(status), 52 error(event, path / "occ_error", callBack), 53 ffdc(event, path / "ffdc", instance), 54 presence(event, path / "occs_present", manager, callBack), 55 throttleProcTemp( 56 event, path / "occ_dvfs_overtemp", 57 std::bind(std::mem_fn(&Device::throttleProcTempCallback), this, 58 std::placeholders::_1)), 59 throttleProcPower( 60 event, path / "occ_dvfs_power", 61 std::bind(std::mem_fn(&Device::throttleProcPowerCallback), this, 62 std::placeholders::_1)), 63 throttleMemTemp(event, path / "occ_mem_throttle", 64 std::bind(std::mem_fn(&Device::throttleMemTempCallback), 65 this, std::placeholders::_1)) 66 { 67 // Nothing to do here 68 } 69 70 /** @brief Binds device to the OCC driver */ 71 inline void bind() 72 { 73 // Bind the device 74 return write(bindPath, config); 75 } 76 77 /** @brief Un-binds device from the OCC driver */ 78 inline void unBind() 79 { 80 // Unbind the device 81 return write(unBindPath, config); 82 } 83 84 /** @brief Returns if device is already bound. 85 * 86 * On device bind, a soft link by the name $config 87 * gets created in OCC_HWMON_PATH and gets removed 88 * on unbind 89 * 90 * @return true if bound, else false 91 */ 92 inline bool bound() const 93 { 94 return fs::exists(OCC_HWMON_PATH + config); 95 } 96 97 /** @brief Starts to monitor for errors 98 * 99 * @param[in] poll - Indicates whether or not the error file should 100 * actually be polled for changes. Disabling polling is 101 * necessary for error files that don't support the poll 102 * file operation. 103 */ 104 inline void addErrorWatch(bool poll = true) 105 { 106 try 107 { 108 throttleProcTemp.addWatch(poll); 109 } 110 catch (const OpenFailure& e) 111 { 112 // try the old kernel version 113 throttleProcTemp.setFile(devPath / "occ_dvfs_ot"); 114 throttleProcTemp.addWatch(poll); 115 } 116 117 throttleProcPower.addWatch(poll); 118 throttleMemTemp.addWatch(poll); 119 120 try 121 { 122 ffdc.addWatch(poll); 123 } 124 catch (const OpenFailure& e) 125 { 126 // nothing to do if there is no FFDC file 127 } 128 129 error.addWatch(poll); 130 } 131 132 /** @brief stops monitoring for errors */ 133 inline void removeErrorWatch() 134 { 135 // we can always safely remove watch even if we don't add it 136 presence.removeWatch(); 137 ffdc.removeWatch(); 138 error.removeWatch(); 139 throttleMemTemp.removeWatch(); 140 throttleProcPower.removeWatch(); 141 throttleProcTemp.removeWatch(); 142 } 143 144 /** @brief Starts to watch how many OCCs are present on the master */ 145 inline void addPresenceWatchMaster() 146 { 147 if (master()) 148 { 149 presence.addWatch(); 150 } 151 } 152 153 /** @brief helper function to get the last part of the path 154 * 155 * @param[in] path - Path to parse 156 * @return - Last directory name in the path 157 */ 158 static std::string getPathBack(const fs::path& path); 159 160 /** @brief Returns true if device represents the master OCC */ 161 bool master() const; 162 163 private: 164 /** @brief Config value to be used to do bind and unbind */ 165 const std::string config; 166 167 /** @brief This directory contains the error files */ 168 const fs::path devPath; 169 170 /** @brief To bind the device to the OCC driver, do: 171 * 172 * Write occ<#>-dev0 to: /sys/bus/platform/drivers/occ-hwmon/bind 173 */ 174 static fs::path bindPath; 175 176 /** @brief To un-bind the device from the OCC driver, do: 177 * Write occ<#>-dev0 to: /sys/bus/platform/drivers/occ-hwmon/unbind 178 */ 179 static fs::path unBindPath; 180 181 /** Store the associated Status instance */ 182 Status& statusObject; 183 184 /** Abstraction of error monitoring */ 185 Error error; 186 187 /** SBE FFDC monitoring */ 188 FFDC ffdc; 189 190 /** Abstraction of OCC presence monitoring */ 191 Presence presence; 192 193 /** Error instances for watching for throttling events */ 194 Error throttleProcTemp; 195 Error throttleProcPower; 196 Error throttleMemTemp; 197 198 /** @brief file writer to achieve bind and unbind 199 * 200 * @param[in] filename - Name of file to be written 201 * @param[in] data - Data to be written to 202 * @return - None 203 */ 204 void write(const fs::path& fileName, const std::string& data) 205 { 206 // If there is an error, move the exception all the way up 207 std::ofstream file(fileName, std::ios::out); 208 file << data; 209 file.close(); 210 return; 211 } 212 213 /** @brief callback for the proc temp throttle event 214 * 215 * @param[in] error - True if an error is reported, false otherwise 216 */ 217 void throttleProcTempCallback(bool error); 218 219 /** @brief callback for the proc power throttle event 220 * 221 * @param[in] error - True if an error is reported, false otherwise 222 */ 223 void throttleProcPowerCallback(bool error); 224 225 /** @brief callback for the proc temp throttle event 226 * 227 * @param[in] error - True if an error is reported, false otherwise 228 */ 229 void throttleMemTempCallback(bool error); 230 }; 231 232 } // namespace occ 233 } // namespace open_power 234