1 #pragma once 2 #include "new_power_supply.hpp" 3 #include "types.hpp" 4 #include "utility.hpp" 5 6 #include <phosphor-logging/lg2.hpp> 7 #include <sdbusplus/bus.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 #include <filesystem> 16 #include <map> 17 #include <string> 18 #include <vector> 19 20 struct SupportedPsuConfiguration 21 { 22 int powerSupplyCount; 23 std::vector<uint64_t> inputVoltage; 24 bool powerConfigFullLoad; 25 }; 26 27 using namespace phosphor::power::psu; 28 using namespace phosphor::power::util; 29 using namespace sdeventplus; 30 31 namespace phosphor::power::chassis 32 { 33 34 constexpr uint64_t invalidObjectPathUniqueId = 9999; 35 using PowerSystemInputsInterface = sdbusplus::xyz::openbmc_project::State:: 36 Decorator::server::PowerSystemInputs; 37 using PowerSystemInputsObject = 38 sdbusplus::server::object_t<PowerSystemInputsInterface>; 39 40 // Validation timeout. Allow 30s to detect if new EM interfaces show up in D-Bus 41 // before performing the validation. 42 // Previously the timer was set to 10 seconds was too short, it results in 43 // incorrect errors being logged, but no real consequence of longer timeout. 44 constexpr auto validationTimeout = std::chrono::seconds(30); 45 46 /** 47 * @class PowerSystemInputs 48 * @brief A concrete implementation for the PowerSystemInputs interface. 49 */ 50 class PowerSystemInputs : public PowerSystemInputsObject 51 { 52 public: PowerSystemInputs(sdbusplus::bus_t & bus,const std::string & path)53 PowerSystemInputs(sdbusplus::bus_t& bus, const std::string& path) : 54 PowerSystemInputsObject(bus, path.c_str()) 55 {} 56 }; 57 58 /** 59 * @class Chassis 60 * 61 * @brief This class will create an object used to manage and monitor a list of 62 * power supply devices attached to the chassis. 63 */ 64 class Chassis 65 { 66 public: 67 Chassis() = delete; 68 ~Chassis() = default; 69 Chassis(const Chassis&) = delete; 70 Chassis& operator=(const Chassis&) = delete; 71 Chassis(Chassis&&) = delete; 72 Chassis& operator=(Chassis&&) = delete; 73 74 /** 75 * @brief Constructor to read configuration from D-Bus. 76 * 77 * @param[in] bus - D-Bus bus object 78 * @param[in] chassisPath - Chassis path 79 * @param[in] event - Event loop object 80 */ 81 Chassis(sdbusplus::bus_t& bus, const std::string& chassisPath, 82 const sdeventplus::Event& e); 83 84 /** 85 * @brief Retrieves the unique identifier of the chassis. 86 * 87 * @return uint64_t The unique 64 bits identifier of the chassis. 88 */ getChassisId()89 uint64_t getChassisId() 90 { 91 return chassisPathUniqueId; 92 } 93 94 /** 95 * @brief Analyze the status of each of the power supplies. Log errors for 96 * faults, when and where appropriate. 97 */ 98 void analyze(); 99 100 /** 101 * @brief Get the status of Power on. 102 */ isPowerOn()103 bool isPowerOn() 104 { 105 return powerOn; 106 } 107 108 /** 109 * @brief Initialize power monitoring infrastructure for Chassis. 110 * Sets up configuration validation timer, attempts to create GPIO, 111 * subscribe to D-Bus power state change events. 112 */ 113 void initPowerMonitoring(); 114 115 /** 116 * @brief Handles addition of the SupportedConfiguration interface. 117 * This function triggered when the SupportedConfiguration interface added 118 * to a D-Bus object. The function calls populateSupportedConfiguration() 119 * and updateMissingPSUs() to processes the provided properties. 120 * 121 * @param properties A map of D-Bus properties associated with the 122 * SupportedConfiguration interface. 123 */ 124 void supportedConfigurationInterfaceAdded( 125 const util::DbusPropertyMap& properties); 126 127 /** 128 * @brief Handle the addition of PSU interface. 129 * This function is called when a Power Supply interface added to a D-Bus. 130 * This function calls getPSUProperties() and updateMissingPSUs(). 131 * 132 * @param properties A map of D-Bus properties for the PSU interface. 133 */ 134 void psuInterfaceAdded(util::DbusPropertyMap& properties); 135 136 /** 137 * @brief Call to validate the psu configuration if the power is on and both 138 * the IBMCFFPSConnector and SupportedConfiguration interfaces have been 139 * processed 140 */ validatePsuConfigAndInterfacesProcessed()141 void validatePsuConfigAndInterfacesProcessed() 142 { 143 if (powerOn && !psus.empty() && !supportedConfigs.empty()) 144 { 145 validationTimer->restartOnce(validationTimeout); 146 } 147 }; 148 149 private: 150 /** 151 * @brief The D-Bus object 152 */ 153 sdbusplus::bus_t& bus; 154 155 /** 156 * @brief The timer that performs power supply validation as the entity 157 * manager interfaces show up in d-bus. 158 */ 159 std::unique_ptr< 160 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>> 161 validationTimer; 162 163 /** @brief True if the power is on. */ 164 bool powerOn = false; 165 166 /** @brief True if power control is in the window between chassis pgood loss 167 * and power off. 168 */ 169 bool powerFaultOccurring = false; 170 171 /** @brief True if an error for a brownout has already been logged. */ 172 bool brownoutLogged = false; 173 174 /** @brief Used as part of subscribing to power on state changes*/ 175 std::string powerService; 176 177 /** @brief Used to subscribe to D-Bus power on state changes */ 178 std::unique_ptr<sdbusplus::bus::match_t> powerOnMatch; 179 180 /** @brief Used to subscribe to D-Bus power supply presence changes */ 181 std::vector<std::unique_ptr<sdbusplus::bus::match_t>> presenceMatches; 182 183 /** 184 * @brief Flag to indicate if the validateConfig() function should be run. 185 * Set to false once the configuration has been validated to avoid 186 * running multiple times due to interfaces added signal. Set to 187 * true during power off to trigger the validation on power on. 188 */ 189 bool runValidateConfig = true; 190 191 /** 192 * @brief Map of supported PSU configurations that include the model name 193 * and their properties. 194 */ 195 std::map<std::string, SupportedPsuConfiguration> supportedConfigs; 196 197 /** 198 * @brief The vector for power supplies. 199 */ 200 std::vector<std::unique_ptr<PowerSupply>> psus; 201 202 /** 203 * @brief The device driver name for all power supplies. 204 */ 205 std::string driverName; 206 207 /** 208 * @brief The libgpiod object for setting the power supply config 209 */ 210 std::unique_ptr<GPIOInterfaceBase> powerConfigGPIO = nullptr; 211 212 /** 213 * @brief Chassis D-Bus object path 214 */ 215 std::string chassisPath; 216 217 /** 218 * @brief Chassis name; 219 */ 220 std::string chassisShortName; 221 222 /** 223 * @brief The Chassis path unique ID 224 * 225 * Note: chassisPathUniqueId must be declared before powerSystemInputs. 226 */ 227 uint64_t chassisPathUniqueId = invalidObjectPathUniqueId; 228 229 /** 230 * @brief PowerSystemInputs object 231 */ 232 PowerSystemInputs powerSystemInputs; 233 234 /** 235 * @brief Declares a constant reference to an sdeventplus::Event to manage 236 * async processing. 237 */ 238 const sdeventplus::Event& eventLoop; 239 240 /** 241 * @brief GPIO to toggle to 'sync' power supply input history. 242 */ 243 std::unique_ptr<GPIOInterfaceBase> syncHistoryGPIO = nullptr; 244 245 /** 246 * @brief Get PSU properties from D-Bus, use that to build a power supply 247 * object. 248 * 249 * @param[in] properties - A map of property names and values 250 */ 251 void getPSUProperties(util::DbusPropertyMap& properties); 252 253 /** 254 * @brief Get PSU configuration from D-Bus 255 */ 256 void getPSUConfiguration(); 257 258 /** 259 * @brief Queries D-Bus for chassis configuration provided by the Entity 260 * Manager. Matches the object against the current chassis unique ID. Upon 261 * finding a match calls populateSupportedConfiguration(). 262 */ 263 void getSupportedConfiguration(); 264 265 /** 266 * @brief Callback for inventory property changes 267 * 268 * Process change of the Power Supply presence. 269 * 270 * @param[in] msg - Data associated with the Present change signal 271 **/ 272 void psuPresenceChanged(sdbusplus::message_t& msg); 273 274 /** 275 * @brief Helper function to populate the PSU supported configuration 276 * 277 * @param[in] properties - A map of property names and values 278 */ 279 void populateSupportedConfiguration( 280 const util::DbusPropertyMap& properties); 281 282 /** 283 * @brief Build the device driver name for the power supply. 284 * 285 * @param[in] i2cbus - i2c bus 286 * @param[in] i2caddr - i2c bus address 287 */ 288 void buildDriverName(uint64_t i2cbus, uint64_t i2caddr); 289 290 /** 291 * @brief Find PSU with device driver name, then populate the device 292 * driver name to all PSUs (including missing PSUs). 293 */ 294 void populateDriverName(); 295 296 /** 297 * @brief Get chassis path unique ID. 298 * 299 * @param [in] path - Chassis path. 300 * @return uint64_t - Chassis path unique ID. 301 */ 302 uint64_t getChassisPathUniqueId(const std::string& path); 303 304 /** 305 * @brief Initializes the chassis. 306 * 307 */ initialize()308 void initialize() {}; // TODO 309 310 /** 311 * @brief Perform power supply configuration validation. 312 * @details Validates if the existing power supply properties are a 313 * supported configuration, and acts on its findings such as logging 314 * errors. 315 */ 316 void validateConfig(); 317 318 /** 319 * @brief Analyze the set of the power supplies for a brownout failure. Log 320 * error when necessary, clear brownout condition when window has passed. 321 */ 322 void analyzeBrownout(); 323 324 /** 325 * @brief Toggles the GPIO to sync power supply input history readings 326 * @details This GPIO is connected to all supplies. This will clear the 327 * previous readings out of the supplies and restart them both at the 328 * same time zero and at record ID 0. The supplies will return 0 329 * bytes of data for the input history command right after this until 330 * a new entry shows up. 331 * 332 * This will cause the code to delete all previous history data and 333 * start fresh. 334 */ 335 void syncHistory(); 336 337 /** 338 * @brief Tells each PSU to set its power supply input 339 * voltage rating D-Bus property. 340 */ setInputVoltageRating()341 inline void setInputVoltageRating() 342 { 343 for (auto& psu : psus) 344 { 345 psu->setInputVoltageRating(); 346 } 347 } 348 349 /** 350 * Create an error 351 * 352 * @param[in] faultName - 'name' message for the BMC error log entry 353 * @param[in,out] additionalData - The AdditionalData property for the error 354 */ 355 void createError(const std::string& faultName, 356 std::map<std::string, std::string>& additionalData); 357 358 /** 359 * @brief Check that all PSUs have the same model name and that the system 360 * has the required number of PSUs present as specified in the Supported 361 * Configuration interface. 362 * 363 * @param[out] additionalData - Contains debug information on why the check 364 * might have failed. Can be used to fill in error logs. 365 * @return true if all the required PSUs are present, false otherwise. 366 */ 367 bool hasRequiredPSUs(std::map<std::string, std::string>& additionalData); 368 369 /** 370 * @brief Update inventory for missing required power supplies 371 */ 372 void updateMissingPSUs(); 373 374 /** 375 * @brief Assign chassis short name. 376 */ saveChassisName()377 void saveChassisName() 378 { 379 std::filesystem::path path(chassisPath); 380 chassisShortName = path.filename(); 381 } 382 383 /** 384 * @brief Callback for power state property changes 385 * 386 * Process changes to the powered on state property for the chassis. 387 * 388 * @param[in] msg - Data associated with the power state signal 389 */ 390 void powerStateChanged(sdbusplus::message_t& msg); 391 392 /** 393 * @breif Attempt to create GPIO 394 */ 395 void attemptToCreatePowerConfigGPIO(); 396 }; 397 398 } // namespace phosphor::power::chassis 399