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