1 #pragma once 2 3 #include <fstream> 4 #include <experimental/filesystem> 5 #include "occ_events.hpp" 6 #include "occ_errors.hpp" 7 #include "occ_presence.hpp" 8 #include "config.h" 9 10 namespace open_power 11 { 12 namespace occ 13 { 14 15 class Manager; 16 class Status; 17 namespace fs = std::experimental::filesystem; 18 19 /** @class Device 20 * @brief Binds and unbinds the OCC driver upon request 21 */ 22 class Device 23 { 24 public: 25 Device() = delete; 26 ~Device() = default; 27 Device(const Device&) = delete; 28 Device& operator=(const Device&) = delete; 29 Device(Device&&) = default; 30 Device& operator=(Device&&) = default; 31 32 /** @brief Constructs the Device object 33 * 34 * @param[in] event - Unique ptr reference to sd_event 35 * @param[in] name - OCC instance name 36 * @param[in] manager - OCC manager instance 37 * @param[in] callback - Optional callback on errors 38 */ 39 Device(EventPtr& event, 40 const std::string& name, 41 const Manager& manager, 42 Status& status, 43 std::function<void(bool)> callBack = nullptr) : 44 #ifdef I2C_OCC 45 config(name), 46 #else 47 config(name + '-' + "dev0"), 48 #endif 49 errorFile(fs::path(config) / "occ_error"), 50 statusObject(status), 51 error(event, errorFile, callBack), 52 presence(event, 53 fs::path(config) / "occs_present", 54 manager, 55 callBack), 56 throttleProcTemp( 57 event, 58 fs::path(config) / "occ_dvfs_ot", 59 std::bind(std::mem_fn(&Device::throttleProcTempCallback), 60 this, 61 std::placeholders::_1)), 62 throttleProcPower( 63 event, 64 fs::path(config) / "occ_dvfs_power", 65 std::bind(std::mem_fn(&Device::throttleProcPowerCallback), 66 this, 67 std::placeholders::_1)), 68 throttleMemTemp( 69 event, 70 fs::path(config) / "occ_mem_throttle", 71 std::bind(std::mem_fn(&Device::throttleMemTempCallback), 72 this, 73 std::placeholders::_1)) 74 { 75 // Nothing to do here 76 } 77 78 /** @brief Binds device to the OCC driver */ 79 inline void bind() 80 { 81 // Bind the device 82 return write(bindPath, config); 83 } 84 85 /** @brief Un-binds device from the OCC driver */ 86 inline void unBind() 87 { 88 // Unbind the device 89 return write(unBindPath, config); 90 } 91 92 /** @brief Returns if device is already bound. 93 * 94 * On device bind, a soft link by the name $config 95 * gets created in OCC_HWMON_PATH and gets removed 96 * on unbind 97 * 98 * @return true if bound, else false 99 */ 100 inline bool bound() const 101 { 102 return fs::exists(OCC_HWMON_PATH + config); 103 } 104 105 /** @brief Starts to monitor for errors */ 106 inline void addErrorWatch() 107 { 108 if (master()) 109 { 110 presence.addWatch(); 111 } 112 113 throttleProcTemp.addWatch(); 114 throttleProcPower.addWatch(); 115 throttleMemTemp.addWatch(); 116 error.addWatch(); 117 } 118 119 /** @brief stops monitoring for errors */ 120 inline void removeErrorWatch() 121 { 122 // we can always safely remove watch even if we don't add it 123 presence.removeWatch(); 124 error.removeWatch(); 125 error.removeWatch(); 126 throttleMemTemp.removeWatch(); 127 throttleProcPower.removeWatch(); 128 throttleProcTemp.removeWatch(); 129 } 130 131 private: 132 /** @brief Config value to be used to do bind and unbind */ 133 const std::string config; 134 135 /** @brief This file contains 0 for success, non-zero for errors */ 136 const fs::path errorFile; 137 138 /** @brief To bind the device to the OCC driver, do: 139 * 140 * Write occ<#>-dev0 to: /sys/bus/platform/drivers/occ-hwmon/bind 141 */ 142 static fs::path bindPath; 143 144 /** @brief To un-bind the device from the OCC driver, do: 145 * Write occ<#>-dev0 to: /sys/bus/platform/drivers/occ-hwmon/unbind 146 */ 147 static fs::path unBindPath; 148 149 /** Store the associated Status instance */ 150 Status& statusObject; 151 152 /** Abstraction of error monitoring */ 153 Error error; 154 155 /** Abstraction of OCC presence monitoring */ 156 Presence presence; 157 158 /** Error instances for watching for throttling events */ 159 Error throttleProcTemp; 160 Error throttleProcPower; 161 Error throttleMemTemp; 162 163 /** @brief file writer to achieve bind and unbind 164 * 165 * @param[in] filename - Name of file to be written 166 * @param[in] data - Data to be written to 167 * @return - None 168 */ 169 void write(const fs::path& fileName, const std::string& data) 170 { 171 // If there is an error, move the exception all the way up 172 std::ofstream file(fileName, std::ios::out); 173 file << data; 174 file.close(); 175 return; 176 } 177 178 /** @brief Returns if device represents the master OCC */ 179 bool master() const; 180 181 /** @brief callback for the proc temp throttle event 182 * 183 * @param[in] error - True if an error is reported, false otherwise 184 */ 185 void throttleProcTempCallback(bool error); 186 187 /** @brief callback for the proc power throttle event 188 * 189 * @param[in] error - True if an error is reported, false otherwise 190 */ 191 void throttleProcPowerCallback(bool error); 192 193 /** @brief callback for the proc temp throttle event 194 * 195 * @param[in] error - True if an error is reported, false otherwise 196 */ 197 void throttleMemTempCallback(bool error); 198 }; 199 200 } // namespace occ 201 } // namespace open_power 202