1 #pragma once 2 3 #include "occ_pass_through.hpp" 4 #include "occ_status.hpp" 5 #ifdef PLDM 6 #include "pldm.hpp" 7 #endif 8 #include "powercap.hpp" 9 #include "utils.hpp" 10 #ifdef POWER10 11 #include "powermode.hpp" 12 #endif 13 14 #include <sdbusplus/bus.hpp> 15 #include <sdeventplus/event.hpp> 16 #include <sdeventplus/utility/timer.hpp> 17 18 #include <cstring> 19 #include <functional> 20 #include <vector> 21 22 namespace sdbusRule = sdbusplus::bus::match::rules; 23 namespace open_power 24 { 25 namespace occ 26 { 27 28 #ifdef READ_OCC_SENSORS 29 enum occFruType 30 { 31 processorCore = 0, 32 internalMemCtlr = 1, 33 dimm = 2, 34 memCtrlAndDimm = 3, 35 VRMVdd = 6, 36 PMIC = 7, 37 memCtlrExSensor = 8 38 }; 39 #endif 40 41 /** @brief Default time, in seconds, between OCC poll commands */ 42 #ifndef POWER10 43 constexpr unsigned int defaultPollingInterval = 1; 44 #else 45 constexpr unsigned int defaultPollingInterval = 5; 46 #endif 47 48 /** @class Manager 49 * @brief Builds and manages OCC objects 50 */ 51 struct Manager 52 { 53 public: 54 Manager() = delete; 55 Manager(const Manager&) = delete; 56 Manager& operator=(const Manager&) = delete; 57 Manager(Manager&&) = delete; 58 Manager& operator=(Manager&&) = delete; 59 ~Manager() = default; 60 61 /** @brief Adds OCC pass-through and status objects on the bus 62 * when corresponding CPU inventory is created. 63 * 64 * @param[in] event - Unique ptr reference to sd_event 65 */ 66 Manager(EventPtr& event) : 67 event(event), pollInterval(defaultPollingInterval), 68 sdpEvent(sdeventplus::Event::get_default()), 69 _pollTimer( 70 std::make_unique< 71 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>( 72 sdpEvent, std::bind(&Manager::pollerTimerExpired, this))) 73 #ifdef PLDM 74 , 75 pldmHandle(std::make_unique<pldm::Interface>( 76 std::bind(std::mem_fn(&Manager::updateOCCActive), this, 77 std::placeholders::_1, std::placeholders::_2))) 78 #endif 79 #ifdef POWER10 80 , 81 discoverTimer( 82 std::make_unique< 83 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>( 84 sdpEvent, std::bind(&Manager::findAndCreateObjects, this))) 85 #endif 86 { 87 #ifdef I2C_OCC 88 // I2C OCC status objects are initialized directly 89 initStatusObjects(); 90 #else 91 findAndCreateObjects(); 92 #endif 93 } 94 95 /** @brief Return the number of bound OCCs */ 96 inline auto getNumOCCs() const 97 { 98 return activeCount; 99 } 100 101 private: 102 /** @brief Creates the OCC D-Bus objects. 103 */ 104 void findAndCreateObjects(); 105 106 /** @brief Callback that responds to cpu creation in the inventory - 107 * by creating the needed objects. 108 * 109 * @param[in] msg - bus message 110 * 111 * @returns 0 to indicate success 112 */ 113 int cpuCreated(sdbusplus::message::message& msg); 114 115 /** @brief Create child OCC objects. 116 * 117 * @param[in] occ - the occ name, such as occ0. 118 */ 119 void createObjects(const std::string& occ); 120 121 /** @brief Callback handler invoked by Status object when the OccActive 122 * property is changed. This is needed to make sure that the 123 * error detection is started only after all the OCCs are bound. 124 * Similarly, when one of the OCC gets its OccActive property 125 * un-set, then the OCC error detection needs to be stopped on 126 * all the OCCs 127 * 128 * @param[in] status - OccActive status 129 */ 130 void statusCallBack(bool status); 131 132 /** @brief Sends a Heartbeat command to host control command handler */ 133 void sendHeartBeat(); 134 135 /** @brief reference to sd_event wrapped in unique_ptr */ 136 EventPtr& event; 137 138 /** @brief OCC pass-through objects */ 139 std::vector<std::unique_ptr<PassThrough>> passThroughObjects; 140 141 /** @brief OCC Status objects */ 142 std::vector<std::unique_ptr<Status>> statusObjects; 143 144 /** @brief Power cap monitor and occ notification object */ 145 std::unique_ptr<open_power::occ::powercap::PowerCap> pcap; 146 147 #ifdef POWER10 148 /** @brief Power mode monitor and notification object */ 149 std::unique_ptr<open_power::occ::powermode::PowerMode> pmode; 150 151 /** @brief Idle Power Saver monitor and notification object */ 152 std::unique_ptr<open_power::occ::powermode::PowerIPS> pips; 153 #endif 154 155 /** @brief sbdbusplus match objects */ 156 std::vector<sdbusplus::bus::match_t> cpuMatches; 157 158 /** @brief Number of OCCs that are bound */ 159 uint8_t activeCount = 0; 160 161 /** @brief Number of seconds between poll commands */ 162 uint8_t pollInterval; 163 164 /** @brief Poll timer event */ 165 sdeventplus::Event sdpEvent; 166 167 /** 168 * @brief The timer to be used once the OCC goes active. When it expires, 169 * a POLL command will be sent to the OCC and then timer restarted. 170 */ 171 std::unique_ptr< 172 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>> 173 _pollTimer; 174 175 #ifdef I2C_OCC 176 /** @brief Init Status objects for I2C OCC devices 177 * 178 * It iterates in /sys/bus/i2c/devices, finds all occ hwmon devices 179 * and creates status objects. 180 */ 181 void initStatusObjects(); 182 #endif 183 184 #ifdef PLDM 185 /** @brief Callback handler invoked by the PLDM event handler when state of 186 * the OCC is toggled by the host. The caller passes the instance 187 * of the OCC and state of the OCC. 188 * 189 * @param[in] instance - instance of the OCC 190 * @param[in] status - true when the OCC goes active and false when the OCC 191 * goes inactive 192 * 193 * @return true if setting the state of OCC is successful and false if it 194 * fails. 195 */ 196 bool updateOCCActive(instanceID instance, bool status); 197 198 std::unique_ptr<pldm::Interface> pldmHandle = nullptr; 199 #endif 200 201 #ifdef POWER10 202 /** 203 * @brief Timer used when discovering OCCs in /dev. 204 */ 205 std::unique_ptr< 206 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>> 207 discoverTimer; 208 209 /** 210 * @brief Used when discovering /dev/occ objects to know if 211 * any were added since the last check. 212 */ 213 std::vector<int> prevOCCSearch; 214 #endif 215 216 /** 217 * @brief Called when poll timer expires and forces a POLL command to the 218 * OCC. The poll timer will then be restarted. 219 * */ 220 void pollerTimerExpired(); 221 222 /** 223 * @brief Finds the OCC devices in /dev 224 * 225 * @return The IDs of the OCCs - 0, 1, etc. 226 */ 227 std::vector<int> findOCCsInDev(); 228 229 #ifdef READ_OCC_SENSORS 230 /** 231 * @brief Gets the occ sensor values. 232 * @param[in] id - Id of the OCC. 233 * @param[in] masterOcc - Is this OCC the master OCC. 234 * */ 235 void getSensorValues(uint32_t id, bool masterOcc); 236 237 /** 238 * @brief Trigger OCC driver to read the temperature sensors. 239 * @param[in] path - path of the OCC sensors. 240 * @param[in] id - Id of the OCC. 241 * */ 242 void readTempSensors(const fs::path& path, uint32_t id); 243 244 /** 245 * @brief Trigger OCC driver to read the power sensors. 246 * @param[in] path - path of the OCC sensors. 247 * @param[in] id - Id of the OCC. 248 * */ 249 void readPowerSensors(const fs::path& path, uint32_t id); 250 251 /** 252 * @brief Set all sensor values of this OCC to NaN. 253 * @param[in] id - Id of the OCC. 254 * */ 255 void setSensorValueToNaN(uint32_t id); 256 257 /** @brief Store the existing OCC sensors on D-BUS */ 258 std::map<std::string, uint32_t> existingSensors; 259 260 /** @brief Get FunctionID from the `powerX_label` file. 261 * @param[in] value - the value of the `powerX_label` file. 262 * @returns FunctionID of the power sensors. 263 */ 264 std::optional<std::string> 265 getPowerLabelFunctionID(const std::string& value); 266 267 /** @brief The power sensor names map */ 268 const std::map<std::string, std::string> powerSensorName = { 269 {"system", "total_power"}, {"1", "p0_mem_power"}, 270 {"2", "p1_mem_power"}, {"3", "p2_mem_power"}, 271 {"4", "p3_mem_power"}, {"5", "p0_power"}, 272 {"6", "p1_power"}, {"7", "p2_power"}, 273 {"8", "p3_power"}, {"9", "p0_cache_power"}, 274 {"10", "p1_cache_power"}, {"11", "p2_cache_power"}, 275 {"12", "p3_cache_power"}, {"13", "io_a_power"}, 276 {"14", "io_b_power"}, {"15", "io_c_power"}, 277 {"16", "fans_a_power"}, {"17", "fans_b_power"}, 278 {"18", "storage_a_power"}, {"19", "storage_b_power"}, 279 {"23", "mem_cache_power"}, {"25", "p0_mem_0_power"}, 280 {"26", "p0_mem_1_power"}, {"27", "p0_mem_2_power"}}; 281 282 /** @brief The dimm temperature sensor names map */ 283 const std::map<uint32_t, std::string> dimmTempSensorName = { 284 {internalMemCtlr, "_intmb_temp"}, 285 {dimm, "_dram_temp"}, 286 {memCtrlAndDimm, "_dram_extmb_temp"}, 287 {PMIC, "_pmic_temp"}, 288 {memCtlrExSensor, "_extmb_temp"}}; 289 #endif 290 }; 291 292 } // namespace occ 293 } // namespace open_power 294