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