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 #endif 151 152 /** @brief sbdbusplus match objects */ 153 std::vector<sdbusplus::bus::match_t> cpuMatches; 154 155 /** @brief Number of OCCs that are bound */ 156 uint8_t activeCount = 0; 157 158 /** @brief Number of seconds between poll commands */ 159 uint8_t pollInterval; 160 161 /** @brief Poll timer event */ 162 sdeventplus::Event sdpEvent; 163 164 /** 165 * @brief The timer to be used once the OCC goes active. When it expires, 166 * a POLL command will be sent to the OCC and then timer restarted. 167 */ 168 std::unique_ptr< 169 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>> 170 _pollTimer; 171 172 #ifdef I2C_OCC 173 /** @brief Init Status objects for I2C OCC devices 174 * 175 * It iterates in /sys/bus/i2c/devices, finds all occ hwmon devices 176 * and creates status objects. 177 */ 178 void initStatusObjects(); 179 #endif 180 181 #ifdef PLDM 182 /** @brief Callback handler invoked by the PLDM event handler when state of 183 * the OCC is toggled by the host. The caller passes the instance 184 * of the OCC and state of the OCC. 185 * 186 * @param[in] instance - instance of the OCC 187 * @param[in] status - true when the OCC goes active and false when the OCC 188 * goes inactive 189 * 190 * @return true if setting the state of OCC is successful and false if it 191 * fails. 192 */ 193 bool updateOCCActive(instanceID instance, bool status); 194 195 std::unique_ptr<pldm::Interface> pldmHandle = nullptr; 196 #endif 197 198 #ifdef POWER10 199 /** 200 * @brief Timer used when discovering OCCs in /dev. 201 */ 202 std::unique_ptr< 203 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>> 204 discoverTimer; 205 206 /** 207 * @brief Used when discovering /dev/occ objects to know if 208 * any were added since the last check. 209 */ 210 std::vector<int> prevOCCSearch; 211 #endif 212 213 /** 214 * @brief Called when poll timer expires and forces a POLL command to the 215 * OCC. The poll timer will then be restarted. 216 * */ 217 void pollerTimerExpired(); 218 219 /** 220 * @brief Finds the OCC devices in /dev 221 * 222 * @return The IDs of the OCCs - 0, 1, etc. 223 */ 224 std::vector<int> findOCCsInDev(); 225 226 #ifdef READ_OCC_SENSORS 227 /** 228 * @brief Gets the occ sensor values. 229 * @param[in] id - Id of the OCC. 230 * @param[in] masterOcc - Is this OCC the master OCC. 231 * */ 232 void getSensorValues(uint32_t id, bool masterOcc); 233 234 /** 235 * @brief Trigger OCC driver to read the temperature sensors. 236 * @param[in] path - path of the OCC sensors. 237 * @param[in] id - Id of the OCC. 238 * */ 239 void readTempSensors(const fs::path& path, uint32_t id); 240 241 /** 242 * @brief Trigger OCC driver to read the power sensors. 243 * @param[in] path - path of the OCC sensors. 244 * @param[in] id - Id of the OCC. 245 * */ 246 void readPowerSensors(const fs::path& path, uint32_t id); 247 248 /** 249 * @brief Set all sensor values of this OCC to NaN. 250 * @param[in] id - Id of the OCC. 251 * */ 252 void setSensorValueToNaN(uint32_t id); 253 254 /** @brief Store the existing OCC sensors on D-BUS */ 255 std::map<std::string, uint32_t> existingSensors; 256 257 /** @brief Get FunctionID from the `powerX_label` file. 258 * @param[in] value - the value of the `powerX_label` file. 259 * @returns FunctionID of the power sensors. 260 */ 261 std::optional<std::string> 262 getPowerLabelFunctionID(const std::string& value); 263 264 /** @brief The power sensor names map */ 265 const std::map<std::string, std::string> powerSensorName = { 266 {"system", "total_power"}, {"1", "p0_mem_power"}, 267 {"2", "p1_mem_power"}, {"3", "p2_mem_power"}, 268 {"4", "p3_mem_power"}, {"5", "p0_power"}, 269 {"6", "p1_power"}, {"7", "p2_power"}, 270 {"8", "p3_power"}, {"9", "p0_cache_power"}, 271 {"10", "p1_cache_power"}, {"11", "p2_cache_power"}, 272 {"12", "p3_cache_power"}, {"13", "io_a_power"}, 273 {"14", "io_b_power"}, {"15", "io_c_power"}, 274 {"16", "fans_a_power"}, {"17", "fans_b_power"}, 275 {"18", "storage_a_power"}, {"19", "storage_b_power"}, 276 {"23", "mem_cache_power"}, {"25", "p0_mem_0_power"}, 277 {"26", "p0_mem_1_power"}, {"27", "p0_mem_2_power"}}; 278 279 /** @brief The dimm temperature sensor names map */ 280 const std::map<uint32_t, std::string> dimmTempSensorName = { 281 {internalMemCtlr, "_intmb_temp"}, 282 {dimm, "_dram_temp"}, 283 {memCtrlAndDimm, "_dram_extmb_temp"}, 284 {PMIC, "_pmic_temp"}, 285 {memCtlrExSensor, "_extmb_temp"}}; 286 #endif 287 }; 288 289 } // namespace occ 290 } // namespace open_power 291