blob: 8725ce8bed0bcc0fc7c580b73acd67fede081a93 [file] [log] [blame]
Brandon Wyman2bac8602019-09-12 18:12:21 -05001#pragma once
2
Brandon Wymana0f33ce2019-10-17 18:32:29 -05003#include "power_supply.hpp"
4#include "types.hpp"
5#include "utility.hpp"
6
7#include <phosphor-logging/log.hpp>
Brandon Wyman2bac8602019-09-12 18:12:21 -05008#include <sdbusplus/bus/match.hpp>
Adriana Kobylakc9b05732022-03-19 15:15:10 +00009#include <sdbusplus/server/manager.hpp>
10#include <sdbusplus/server/object.hpp>
Brandon Wyman2bac8602019-09-12 18:12:21 -050011#include <sdeventplus/event.hpp>
12#include <sdeventplus/utility/timer.hpp>
Adriana Kobylakc9b05732022-03-19 15:15:10 +000013#include <xyz/openbmc_project/State/Decorator/PowerSystemInputs/server.hpp>
Brandon Wyman2bac8602019-09-12 18:12:21 -050014
Brandon Wymanaed1f752019-11-25 18:10:52 -060015struct sys_properties
16{
Adriana Kobylakd3a70d92021-06-04 16:24:45 +000017 int powerSupplyCount;
18 std::vector<uint64_t> inputVoltage;
Adriana Kobylak886574c2021-11-01 18:22:28 +000019 bool powerConfigFullLoad;
Brandon Wymanaed1f752019-11-25 18:10:52 -060020};
21
Brandon Wymana0f33ce2019-10-17 18:32:29 -050022using namespace phosphor::power::psu;
23using namespace phosphor::logging;
24
Brandon Wyman63ea78b2020-09-24 16:49:09 -050025namespace phosphor::power::manager
Brandon Wyman2bac8602019-09-12 18:12:21 -050026{
27
Adriana Kobylakc9b05732022-03-19 15:15:10 +000028using PowerSystemInputsInterface = sdbusplus::xyz::openbmc_project::State::
29 Decorator::server::PowerSystemInputs;
30using PowerSystemInputsObject =
31 sdbusplus::server::object_t<PowerSystemInputsInterface>;
32
Adriana Kobylak2aba2b22021-10-11 16:00:05 +000033// Validation timeout. Allow 10s to detect if new EM interfaces show up in D-Bus
34// before performing the validation.
35constexpr auto validationTimeout = std::chrono::seconds(10);
Adriana Kobylaka4d38fa2021-10-05 19:57:47 +000036
Brandon Wyman2bac8602019-09-12 18:12:21 -050037/**
Adriana Kobylakc9b05732022-03-19 15:15:10 +000038 * @class PowerSystemInputs
39 * @brief A concrete implementation for the PowerSystemInputs interface.
40 */
41class 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/**
Brandon Wyman2bac8602019-09-12 18:12:21 -050050 * @class PSUManager
51 *
52 * This class will create an object used to manage and monitor a list of power
53 * supply devices.
54 */
55class 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 /**
Brandon Wyman510acaa2020-11-05 18:32:04 -060066 * 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 /**
Brandon Wyman510acaa2020-11-05 18:32:04 -060074 * 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 /**
Adriana Kobylak9bab9e12021-02-24 15:32:03 -060088 * @brief Initialize the system properties from the Supported Configuration
89 * D-Bus object provided by Entity Manager.
90 */
91 void getSystemProperties();
92
93 /**
Brandon Wyman2bac8602019-09-12 18:12:21 -050094 * Initializes the manager.
95 *
96 * Get current BMC state, ...
97 */
98 void initialize()
99 {
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500100 // 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;
Adriana Kobylaka4d38fa2021-10-05 19:57:47 +0000112 validationTimer->restartOnce(validationTimeout);
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500113 }
114 else
115 {
116 powerOn = false;
Adriana Kobylak8f16fb52021-03-31 15:50:15 +0000117 runValidateConfig = true;
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500118 }
119 }
Patrick Williamsc1d4de52021-10-06 12:45:57 -0500120 catch (const std::exception& e)
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500121 {
122 log<level::INFO>("Failed to get power state. Assuming it is off.");
123 powerOn = false;
Adriana Kobylak8f16fb52021-03-31 15:50:15 +0000124 runValidateConfig = true;
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500125 }
126
Brandon Wyman59a35792020-06-04 12:37:40 -0500127 onOffConfig(phosphor::pmbus::ON_OFF_CONFIG_CONTROL_PIN_ONLY);
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500128 clearFaults();
129 updateInventory();
Adriana Kobylakc0a07582021-10-13 15:52:25 +0000130 setPowerConfigGPIO();
Brandon Wyman2bac8602019-09-12 18:12:21 -0500131 }
132
133 /**
134 * Starts the timer to start monitoring the list of devices.
135 */
136 int run()
137 {
Brandon Wyman2fe51862019-11-25 16:43:21 -0600138 return timer->get_event().loop();
Brandon Wyman2bac8602019-09-12 18:12:21 -0500139 }
140
141 /**
Brandon Wyman59a35792020-06-04 12:37:40 -0500142 * 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 /**
Brandon Wyman2bac8602019-09-12 18:12:21 -0500156 * 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 {
Brandon Wyman10fc6e82022-02-08 20:51:22 +0000163 setPowerSupplyError("");
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500164 for (auto& psu : psus)
165 {
Brandon Wymanaed1f752019-11-25 18:10:52 -0600166 psu->clearFaults();
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500167 }
Brandon Wyman2bac8602019-09-12 18:12:21 -0500168 }
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 */
Brandon Wyman2fe51862019-11-25 16:43:21 -0600179 std::unique_ptr<
180 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>
181 timer;
Brandon Wyman2bac8602019-09-12 18:12:21 -0500182
183 /**
Adriana Kobylaka4d38fa2021-10-05 19:57:47 +0000184 * 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 /**
Brandon Wyman10fc6e82022-02-08 20:51:22 +0000192 * 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 /**
Brandon Wymanb76ab242020-09-16 18:06:06 -0500199 * Create an error
200 *
201 * @param[in] faultName - 'name' message for the BMC error log entry
Brandon Wyman8b662882021-10-08 17:31:51 +0000202 * @param[in,out] additionalData - The AdditionalData property for the error
Brandon Wymanb76ab242020-09-16 18:06:06 -0500203 */
204 void createError(const std::string& faultName,
Brandon Wyman8b662882021-10-08 17:31:51 +0000205 std::map<std::string, std::string>& additionalData);
Brandon Wymanb76ab242020-09-16 18:06:06 -0500206
207 /**
Brandon Wyman2bac8602019-09-12 18:12:21 -0500208 * Analyze the status of each of the power supplies.
Brandon Wymanb76ab242020-09-16 18:06:06 -0500209 *
210 * Log errors for faults, when and where appropriate.
Brandon Wyman2bac8602019-09-12 18:12:21 -0500211 */
Brandon Wyman63ea78b2020-09-24 16:49:09 -0500212 void analyze();
Brandon Wyman2bac8602019-09-12 18:12:21 -0500213
214 /** @brief True if the power is on. */
215 bool powerOn = false;
216
Adriana Kobylak2549d792022-01-26 20:51:30 +0000217 /** @brief True if an error for a brownout has already been logged. */
218 bool brownoutLogged = false;
219
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500220 /** @brief Used as part of subscribing to power on state changes*/
221 std::string powerService;
222
Brandon Wyman2bac8602019-09-12 18:12:21 -0500223 /** @brief Used to subscribe to D-Bus power on state changes */
224 std::unique_ptr<sdbusplus::bus::match_t> powerOnMatch;
225
Adriana Kobylak9ba38232021-11-16 20:27:45 +0000226 /** @brief Used to subscribe to D-Bus power supply presence changes */
227 std::vector<std::unique_ptr<sdbusplus::bus::match_t>> presenceMatches;
228
Adriana Kobylak9bab9e12021-02-24 15:32:03 -0600229 /** @brief Used to subscribe to Entity Manager interfaces added */
230 std::unique_ptr<sdbusplus::bus::match_t> entityManagerIfacesAddedMatch;
231
Brandon Wyman2bac8602019-09-12 18:12:21 -0500232 /**
Brandon Wyman2bac8602019-09-12 18:12:21 -0500233 * @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 /**
Adriana Kobylak9ba38232021-11-16 20:27:45 +0000242 * @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 /**
Brandon Wyman3e429132021-03-18 18:03:14 -0500251 * @brief Callback for entity-manager interface added
Adriana Kobylak9bab9e12021-02-24 15:32:03 -0600252 *
Brandon Wyman3e429132021-03-18 18:03:14 -0500253 * Process the information from the supported configuration and or IBM CFFPS
254 * Connector interface being added.
Adriana Kobylak9bab9e12021-02-24 15:32:03 -0600255 *
256 * @param[in] msg - Data associated with the interfaces added signal
257 */
Brandon Wyman3e429132021-03-18 18:03:14 -0500258 void entityManagerIfaceAdded(sdbusplus::message::message& msg);
Adriana Kobylak9bab9e12021-02-24 15:32:03 -0600259
260 /**
Brandon Wyman2bac8602019-09-12 18:12:21 -0500261 * @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 */
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500269 void updateInventory()
270 {
271 for (auto& psu : psus)
272 {
Brandon Wymanaed1f752019-11-25 18:10:52 -0600273 psu->updateInventory();
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500274 }
275 }
276
277 /**
Adriana Kobylake1074d82021-03-16 20:46:44 +0000278 * @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 /**
Adriana Kobylak8f16fb52021-03-31 15:50:15 +0000285 * @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 /**
Adriana Kobylak4d9aaf92021-06-30 15:27:42 +0000300 * @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 /**
Adriana Kobylak523704d2021-09-21 15:55:41 +0000311 * @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 /**
Adriana Kobylakc0a07582021-10-13 15:52:25 +0000322 * @brief Set the power-config-full-load GPIO depending on the EM full load
323 * property value.
324 */
325 void setPowerConfigGPIO();
326
327 /**
Adriana Kobylake5b1e082022-03-02 15:37:32 +0000328 * @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 /**
Adriana Kobylak9ea66a62021-03-24 17:54:14 +0000343 * @brief Map of supported PSU configurations that include the model name
344 * and their properties.
Brandon Wymanaed1f752019-11-25 18:10:52 -0600345 */
Adriana Kobylakd3a70d92021-06-04 16:24:45 +0000346 std::map<std::string, sys_properties> supportedConfigs;
Brandon Wymanaed1f752019-11-25 18:10:52 -0600347
348 /**
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500349 * @brief The vector for power supplies.
350 */
Brandon Wymanaed1f752019-11-25 18:10:52 -0600351 std::vector<std::unique_ptr<PowerSupply>> psus;
Adriana Kobylakc0a07582021-10-13 15:52:25 +0000352
353 /**
354 * @brief The libgpiod object for setting the power supply config
355 */
356 std::unique_ptr<GPIOInterfaceBase> powerConfigGPIO = nullptr;
Adriana Kobylakc9b05732022-03-19 15:15:10 +0000357
358 /**
359 * @brief PowerSystemInputs object
360 */
361 PowerSystemInputs powerSystemInputs;
362
363 /**
Brandon Wymanc3324422022-03-24 20:30:57 +0000364 * @brief Implement the ObjectManager for PowerSystemInputs object.
365 *
366 * Implements the org.freedesktop.DBus.ObjectManager interface used to
367 * communicate updates to the PowerSystemInputs object on the
368 * /xyz/openbmc_project/power/power_supplies root D-Bus path.
Adriana Kobylakc9b05732022-03-19 15:15:10 +0000369 */
370 sdbusplus::server::manager_t objectManager;
Brandon Wymanc3324422022-03-24 20:30:57 +0000371
372 /**
373 * @brief Implement the ObjectManager for power supply input history.
374 *
375 * Implements the org.freedesktop.DBus.ObjectManager interface used to
376 * communicate updates to the Average and Maximum interface properties on
377 * the /org/open_power/sensors root D-Bus path.
378 */
379 sdbusplus::server::manager_t historyManager;
Brandon Wyman2bac8602019-09-12 18:12:21 -0500380};
381
Brandon Wyman63ea78b2020-09-24 16:49:09 -0500382} // namespace phosphor::power::manager