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