blob: e54f536b84f9f99ad84eb02e132f9af9107f4b3d [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>
9#include <sdeventplus/event.hpp>
10#include <sdeventplus/utility/timer.hpp>
11
Brandon Wymanaed1f752019-11-25 18:10:52 -060012struct sys_properties
13{
Adriana Kobylakd3a70d92021-06-04 16:24:45 +000014 int powerSupplyCount;
15 std::vector<uint64_t> inputVoltage;
Brandon Wymanaed1f752019-11-25 18:10:52 -060016};
17
Brandon Wymana0f33ce2019-10-17 18:32:29 -050018using namespace phosphor::power::psu;
19using namespace phosphor::logging;
20
Brandon Wyman63ea78b2020-09-24 16:49:09 -050021namespace phosphor::power::manager
Brandon Wyman2bac8602019-09-12 18:12:21 -050022{
23
Adriana Kobylak2aba2b22021-10-11 16:00:05 +000024// Validation timeout. Allow 10s to detect if new EM interfaces show up in D-Bus
25// before performing the validation.
26constexpr auto validationTimeout = std::chrono::seconds(10);
Adriana Kobylaka4d38fa2021-10-05 19:57:47 +000027
Brandon Wyman2bac8602019-09-12 18:12:21 -050028/**
29 * @class PSUManager
30 *
31 * This class will create an object used to manage and monitor a list of power
32 * supply devices.
33 */
34class PSUManager
35{
36 public:
37 PSUManager() = delete;
38 ~PSUManager() = default;
39 PSUManager(const PSUManager&) = delete;
40 PSUManager& operator=(const PSUManager&) = delete;
41 PSUManager(PSUManager&&) = delete;
42 PSUManager& operator=(PSUManager&&) = delete;
43
44 /**
Brandon Wyman510acaa2020-11-05 18:32:04 -060045 * Constructor to read configuration from D-Bus.
46 *
47 * @param[in] bus - D-Bus bus object
48 * @param[in] e - event object
49 */
50 PSUManager(sdbusplus::bus::bus& bus, const sdeventplus::Event& e);
51
52 /**
Brandon Wyman510acaa2020-11-05 18:32:04 -060053 * Get PSU properties from D-Bus, use that to build a power supply
54 * object.
55 *
56 * @param[in] properties - A map of property names and values
57 *
58 */
59 void getPSUProperties(util::DbusPropertyMap& properties);
60
61 /**
62 * Get PSU configuration from D-Bus
63 */
64 void getPSUConfiguration();
65
66 /**
Adriana Kobylak9bab9e12021-02-24 15:32:03 -060067 * @brief Initialize the system properties from the Supported Configuration
68 * D-Bus object provided by Entity Manager.
69 */
70 void getSystemProperties();
71
72 /**
Brandon Wyman2bac8602019-09-12 18:12:21 -050073 * Initializes the manager.
74 *
75 * Get current BMC state, ...
76 */
77 void initialize()
78 {
Brandon Wymana0f33ce2019-10-17 18:32:29 -050079 // When state = 1, system is powered on
80 int32_t state = 0;
81
82 try
83 {
84 // Use getProperty utility function to get power state.
85 util::getProperty<int32_t>(POWER_IFACE, "state", POWER_OBJ_PATH,
86 powerService, bus, state);
87
88 if (state)
89 {
90 powerOn = true;
Adriana Kobylaka4d38fa2021-10-05 19:57:47 +000091 validationTimer->restartOnce(validationTimeout);
Brandon Wymana0f33ce2019-10-17 18:32:29 -050092 }
93 else
94 {
95 powerOn = false;
Adriana Kobylak8f16fb52021-03-31 15:50:15 +000096 runValidateConfig = true;
Brandon Wymana0f33ce2019-10-17 18:32:29 -050097 }
98 }
Patrick Williamsc1d4de52021-10-06 12:45:57 -050099 catch (const std::exception& e)
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500100 {
101 log<level::INFO>("Failed to get power state. Assuming it is off.");
102 powerOn = false;
Adriana Kobylak8f16fb52021-03-31 15:50:15 +0000103 runValidateConfig = true;
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500104 }
105
Brandon Wyman59a35792020-06-04 12:37:40 -0500106 onOffConfig(phosphor::pmbus::ON_OFF_CONFIG_CONTROL_PIN_ONLY);
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500107 clearFaults();
108 updateInventory();
Brandon Wyman2bac8602019-09-12 18:12:21 -0500109 }
110
111 /**
112 * Starts the timer to start monitoring the list of devices.
113 */
114 int run()
115 {
Brandon Wyman2fe51862019-11-25 16:43:21 -0600116 return timer->get_event().loop();
Brandon Wyman2bac8602019-09-12 18:12:21 -0500117 }
118
119 /**
Brandon Wyman59a35792020-06-04 12:37:40 -0500120 * Write PMBus ON_OFF_CONFIG
121 *
122 * This function will be called to cause the PMBus device driver to send the
123 * ON_OFF_CONFIG command. Takes one byte of data.
124 */
125 void onOffConfig(const uint8_t data)
126 {
127 for (auto& psu : psus)
128 {
129 psu->onOffConfig(data);
130 }
131 }
132
133 /**
Brandon Wyman2bac8602019-09-12 18:12:21 -0500134 * This function will be called in various situations in order to clear
135 * any fault status bits that may have been set, in order to start over
136 * with a clean state. Presence changes and power state changes will want
137 * to clear any faults logged.
138 */
139 void clearFaults()
140 {
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500141 for (auto& psu : psus)
142 {
Brandon Wymanaed1f752019-11-25 18:10:52 -0600143 psu->clearFaults();
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500144 }
Brandon Wyman2bac8602019-09-12 18:12:21 -0500145 }
146
147 private:
148 /**
149 * The D-Bus object
150 */
151 sdbusplus::bus::bus& bus;
152
153 /**
154 * The timer that runs to periodically check the power supplies.
155 */
Brandon Wyman2fe51862019-11-25 16:43:21 -0600156 std::unique_ptr<
157 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>
158 timer;
Brandon Wyman2bac8602019-09-12 18:12:21 -0500159
160 /**
Adriana Kobylaka4d38fa2021-10-05 19:57:47 +0000161 * The timer that performs power supply validation as the entity manager
162 * interfaces show up in d-bus.
163 */
164 std::unique_ptr<
165 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>
166 validationTimer;
167
168 /**
Brandon Wymanb76ab242020-09-16 18:06:06 -0500169 * Create an error
170 *
171 * @param[in] faultName - 'name' message for the BMC error log entry
Brandon Wyman8b662882021-10-08 17:31:51 +0000172 * @param[in,out] additionalData - The AdditionalData property for the error
Brandon Wymanb76ab242020-09-16 18:06:06 -0500173 */
174 void createError(const std::string& faultName,
Brandon Wyman8b662882021-10-08 17:31:51 +0000175 std::map<std::string, std::string>& additionalData);
Brandon Wymanb76ab242020-09-16 18:06:06 -0500176
177 /**
Brandon Wyman2bac8602019-09-12 18:12:21 -0500178 * Analyze the status of each of the power supplies.
Brandon Wymanb76ab242020-09-16 18:06:06 -0500179 *
180 * Log errors for faults, when and where appropriate.
Brandon Wyman2bac8602019-09-12 18:12:21 -0500181 */
Brandon Wyman63ea78b2020-09-24 16:49:09 -0500182 void analyze();
Brandon Wyman2bac8602019-09-12 18:12:21 -0500183
184 /** @brief True if the power is on. */
185 bool powerOn = false;
186
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500187 /** @brief Used as part of subscribing to power on state changes*/
188 std::string powerService;
189
Brandon Wyman2bac8602019-09-12 18:12:21 -0500190 /** @brief Used to subscribe to D-Bus power on state changes */
191 std::unique_ptr<sdbusplus::bus::match_t> powerOnMatch;
192
Adriana Kobylak9bab9e12021-02-24 15:32:03 -0600193 /** @brief Used to subscribe to Entity Manager interfaces added */
194 std::unique_ptr<sdbusplus::bus::match_t> entityManagerIfacesAddedMatch;
195
Brandon Wyman2bac8602019-09-12 18:12:21 -0500196 /**
Brandon Wyman2bac8602019-09-12 18:12:21 -0500197 * @brief Callback for power state property changes
198 *
199 * Process changes to the powered on state property for the system.
200 *
201 * @param[in] msg - Data associated with the power state signal
202 */
203 void powerStateChanged(sdbusplus::message::message& msg);
204
205 /**
Brandon Wyman3e429132021-03-18 18:03:14 -0500206 * @brief Callback for entity-manager interface added
Adriana Kobylak9bab9e12021-02-24 15:32:03 -0600207 *
Brandon Wyman3e429132021-03-18 18:03:14 -0500208 * Process the information from the supported configuration and or IBM CFFPS
209 * Connector interface being added.
Adriana Kobylak9bab9e12021-02-24 15:32:03 -0600210 *
211 * @param[in] msg - Data associated with the interfaces added signal
212 */
Brandon Wyman3e429132021-03-18 18:03:14 -0500213 void entityManagerIfaceAdded(sdbusplus::message::message& msg);
Adriana Kobylak9bab9e12021-02-24 15:32:03 -0600214
215 /**
Brandon Wyman2bac8602019-09-12 18:12:21 -0500216 * @brief Adds properties to the inventory.
217 *
218 * Reads the values from the devices and writes them to the associated
219 * power supply D-Bus inventory objects.
220 *
221 * This needs to be done on startup, and each time the presence state
222 * changes.
223 */
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500224 void updateInventory()
225 {
226 for (auto& psu : psus)
227 {
Brandon Wymanaed1f752019-11-25 18:10:52 -0600228 psu->updateInventory();
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500229 }
230 }
231
232 /**
Adriana Kobylake1074d82021-03-16 20:46:44 +0000233 * @brief Helper function to populate the system properties
234 *
235 * @param[in] properties - A map of property names and values
236 */
237 void populateSysProperties(const util::DbusPropertyMap& properties);
238
239 /**
Adriana Kobylak8f16fb52021-03-31 15:50:15 +0000240 * @brief Perform power supply configuration validation.
241 * @details Validates if the existing power supply properties are a
242 * supported configuration, and acts on its findings such as logging errors.
243 */
244 void validateConfig();
245
246 /**
247 * @brief Flag to indicate if the validateConfig() function should be run.
248 * Set to false once the configuration has been validated to avoid running
249 * multiple times due to interfaces added signal. Set to true during power
250 * off to trigger the validation on power on.
251 */
252 bool runValidateConfig = true;
253
254 /**
Adriana Kobylak4d9aaf92021-06-30 15:27:42 +0000255 * @brief Check that all PSUs have the same model name and that the system
256 * has the required number of PSUs present as specified in the Supported
257 * Configuration interface.
258 *
259 * @param[out] additionalData - Contains debug information on why the check
260 * might have failed. Can be used to fill in error logs.
261 * @return true if all the required PSUs are present, false otherwise.
262 */
263 bool hasRequiredPSUs(std::map<std::string, std::string>& additionalData);
264
265 /**
Adriana Kobylak523704d2021-09-21 15:55:41 +0000266 * @brief Helper function to validate that all PSUs have the same model name
267 *
268 * @param[out] model - The model name. Empty if there is a mismatch.
269 * @param[out] additionalData - If there is a mismatch, it contains debug
270 * information such as the mismatched model name.
271 * @return true if all the PSUs have the same model name, false otherwise.
272 */
273 bool validateModelName(std::string& model,
274 std::map<std::string, std::string>& additionalData);
275
276 /**
Adriana Kobylak9ea66a62021-03-24 17:54:14 +0000277 * @brief Map of supported PSU configurations that include the model name
278 * and their properties.
Brandon Wymanaed1f752019-11-25 18:10:52 -0600279 */
Adriana Kobylakd3a70d92021-06-04 16:24:45 +0000280 std::map<std::string, sys_properties> supportedConfigs;
Brandon Wymanaed1f752019-11-25 18:10:52 -0600281
282 /**
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500283 * @brief The vector for power supplies.
284 */
Brandon Wymanaed1f752019-11-25 18:10:52 -0600285 std::vector<std::unique_ptr<PowerSupply>> psus;
Brandon Wyman2bac8602019-09-12 18:12:21 -0500286};
287
Brandon Wyman63ea78b2020-09-24 16:49:09 -0500288} // namespace phosphor::power::manager