1 #pragma once 2 3 #include "power_supply.hpp" 4 #include "types.hpp" 5 #include "utility.hpp" 6 7 #include <phosphor-logging/log.hpp> 8 #include <sdbusplus/bus/match.hpp> 9 #include <sdeventplus/event.hpp> 10 #include <sdeventplus/utility/timer.hpp> 11 12 struct sys_properties 13 { 14 int powerSupplyCount; 15 std::vector<uint64_t> inputVoltage; 16 bool powerConfigFullLoad; 17 }; 18 19 using namespace phosphor::power::psu; 20 using namespace phosphor::logging; 21 22 namespace phosphor::power::manager 23 { 24 25 // Validation timeout. Allow 10s to detect if new EM interfaces show up in D-Bus 26 // before performing the validation. 27 constexpr auto validationTimeout = std::chrono::seconds(10); 28 29 /** 30 * @class PSUManager 31 * 32 * This class will create an object used to manage and monitor a list of power 33 * supply devices. 34 */ 35 class PSUManager 36 { 37 public: 38 PSUManager() = delete; 39 ~PSUManager() = default; 40 PSUManager(const PSUManager&) = delete; 41 PSUManager& operator=(const PSUManager&) = delete; 42 PSUManager(PSUManager&&) = delete; 43 PSUManager& operator=(PSUManager&&) = delete; 44 45 /** 46 * Constructor to read configuration from D-Bus. 47 * 48 * @param[in] bus - D-Bus bus object 49 * @param[in] e - event object 50 */ 51 PSUManager(sdbusplus::bus::bus& bus, const sdeventplus::Event& e); 52 53 /** 54 * Get PSU properties from D-Bus, use that to build a power supply 55 * object. 56 * 57 * @param[in] properties - A map of property names and values 58 * 59 */ 60 void getPSUProperties(util::DbusPropertyMap& properties); 61 62 /** 63 * Get PSU configuration from D-Bus 64 */ 65 void getPSUConfiguration(); 66 67 /** 68 * @brief Initialize the system properties from the Supported Configuration 69 * D-Bus object provided by Entity Manager. 70 */ 71 void getSystemProperties(); 72 73 /** 74 * Initializes the manager. 75 * 76 * Get current BMC state, ... 77 */ 78 void initialize() 79 { 80 // When state = 1, system is powered on 81 int32_t state = 0; 82 83 try 84 { 85 // Use getProperty utility function to get power state. 86 util::getProperty<int32_t>(POWER_IFACE, "state", POWER_OBJ_PATH, 87 powerService, bus, state); 88 89 if (state) 90 { 91 powerOn = true; 92 validationTimer->restartOnce(validationTimeout); 93 } 94 else 95 { 96 powerOn = false; 97 runValidateConfig = true; 98 } 99 } 100 catch (const std::exception& e) 101 { 102 log<level::INFO>("Failed to get power state. Assuming it is off."); 103 powerOn = false; 104 runValidateConfig = true; 105 } 106 107 onOffConfig(phosphor::pmbus::ON_OFF_CONFIG_CONTROL_PIN_ONLY); 108 clearFaults(); 109 updateInventory(); 110 setPowerConfigGPIO(); 111 } 112 113 /** 114 * Starts the timer to start monitoring the list of devices. 115 */ 116 int run() 117 { 118 return timer->get_event().loop(); 119 } 120 121 /** 122 * Write PMBus ON_OFF_CONFIG 123 * 124 * This function will be called to cause the PMBus device driver to send the 125 * ON_OFF_CONFIG command. Takes one byte of data. 126 */ 127 void onOffConfig(const uint8_t data) 128 { 129 for (auto& psu : psus) 130 { 131 psu->onOffConfig(data); 132 } 133 } 134 135 /** 136 * This function will be called in various situations in order to clear 137 * any fault status bits that may have been set, in order to start over 138 * with a clean state. Presence changes and power state changes will want 139 * to clear any faults logged. 140 */ 141 void clearFaults() 142 { 143 for (auto& psu : psus) 144 { 145 psu->clearFaults(); 146 } 147 } 148 149 private: 150 /** 151 * The D-Bus object 152 */ 153 sdbusplus::bus::bus& bus; 154 155 /** 156 * The timer that runs to periodically check the power supplies. 157 */ 158 std::unique_ptr< 159 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>> 160 timer; 161 162 /** 163 * The timer that performs power supply validation as the entity manager 164 * interfaces show up in d-bus. 165 */ 166 std::unique_ptr< 167 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>> 168 validationTimer; 169 170 /** 171 * Create an error 172 * 173 * @param[in] faultName - 'name' message for the BMC error log entry 174 * @param[in,out] additionalData - The AdditionalData property for the error 175 */ 176 void createError(const std::string& faultName, 177 std::map<std::string, std::string>& additionalData); 178 179 /** 180 * Analyze the status of each of the power supplies. 181 * 182 * Log errors for faults, when and where appropriate. 183 */ 184 void analyze(); 185 186 /** @brief True if the power is on. */ 187 bool powerOn = false; 188 189 /** @brief Used as part of subscribing to power on state changes*/ 190 std::string powerService; 191 192 /** @brief Used to subscribe to D-Bus power on state changes */ 193 std::unique_ptr<sdbusplus::bus::match_t> powerOnMatch; 194 195 /** @brief Used to subscribe to Entity Manager interfaces added */ 196 std::unique_ptr<sdbusplus::bus::match_t> entityManagerIfacesAddedMatch; 197 198 /** 199 * @brief Callback for power state property changes 200 * 201 * Process changes to the powered on state property for the system. 202 * 203 * @param[in] msg - Data associated with the power state signal 204 */ 205 void powerStateChanged(sdbusplus::message::message& msg); 206 207 /** 208 * @brief Callback for entity-manager interface added 209 * 210 * Process the information from the supported configuration and or IBM CFFPS 211 * Connector interface being added. 212 * 213 * @param[in] msg - Data associated with the interfaces added signal 214 */ 215 void entityManagerIfaceAdded(sdbusplus::message::message& msg); 216 217 /** 218 * @brief Adds properties to the inventory. 219 * 220 * Reads the values from the devices and writes them to the associated 221 * power supply D-Bus inventory objects. 222 * 223 * This needs to be done on startup, and each time the presence state 224 * changes. 225 */ 226 void updateInventory() 227 { 228 for (auto& psu : psus) 229 { 230 psu->updateInventory(); 231 } 232 } 233 234 /** 235 * @brief Helper function to populate the system properties 236 * 237 * @param[in] properties - A map of property names and values 238 */ 239 void populateSysProperties(const util::DbusPropertyMap& properties); 240 241 /** 242 * @brief Perform power supply configuration validation. 243 * @details Validates if the existing power supply properties are a 244 * supported configuration, and acts on its findings such as logging errors. 245 */ 246 void validateConfig(); 247 248 /** 249 * @brief Flag to indicate if the validateConfig() function should be run. 250 * Set to false once the configuration has been validated to avoid running 251 * multiple times due to interfaces added signal. Set to true during power 252 * off to trigger the validation on power on. 253 */ 254 bool runValidateConfig = true; 255 256 /** 257 * @brief Check that all PSUs have the same model name and that the system 258 * has the required number of PSUs present as specified in the Supported 259 * Configuration interface. 260 * 261 * @param[out] additionalData - Contains debug information on why the check 262 * might have failed. Can be used to fill in error logs. 263 * @return true if all the required PSUs are present, false otherwise. 264 */ 265 bool hasRequiredPSUs(std::map<std::string, std::string>& additionalData); 266 267 /** 268 * @brief Helper function to validate that all PSUs have the same model name 269 * 270 * @param[out] model - The model name. Empty if there is a mismatch. 271 * @param[out] additionalData - If there is a mismatch, it contains debug 272 * information such as the mismatched model name. 273 * @return true if all the PSUs have the same model name, false otherwise. 274 */ 275 bool validateModelName(std::string& model, 276 std::map<std::string, std::string>& additionalData); 277 278 /** 279 * @brief Set the power-config-full-load GPIO depending on the EM full load 280 * property value. 281 */ 282 void setPowerConfigGPIO(); 283 284 /** 285 * @brief Map of supported PSU configurations that include the model name 286 * and their properties. 287 */ 288 std::map<std::string, sys_properties> supportedConfigs; 289 290 /** 291 * @brief The vector for power supplies. 292 */ 293 std::vector<std::unique_ptr<PowerSupply>> psus; 294 295 /** 296 * @brief The libgpiod object for setting the power supply config 297 */ 298 std::unique_ptr<GPIOInterfaceBase> powerConfigGPIO = nullptr; 299 }; 300 301 } // namespace phosphor::power::manager 302