blob: db16ac29fcfd437af52593bd06043b6e7b8ca862 [file] [log] [blame]
Faisal Awada348168b2025-07-08 11:23:02 -05001#include "config.h"
2
3#include "chassis_manager.hpp"
4
5#include <phosphor-logging/lg2.hpp>
Faisal Awada9ed0f382025-08-14 13:21:46 -05006
Faisal Awada348168b2025-07-08 11:23:02 -05007using namespace phosphor::logging;
8
9namespace phosphor::power::chassis_manager
10{
11using namespace phosphor::power::util;
12constexpr auto managerBusName =
13 "xyz.openbmc_project.Power.MultiChassisPSUMonitor";
14constexpr auto IBMCFFPSInterface =
15 "xyz.openbmc_project.Configuration.IBMCFFPSConnector";
16constexpr auto supportedConfIntf =
17 "xyz.openbmc_project.Configuration.SupportedConfiguration";
18
19ChassisManager::ChassisManager(sdbusplus::bus_t& bus,
20 const sdeventplus::Event& e) :
21 bus(bus), eventLoop(e)
22{
23 // Subscribe to InterfacesAdded before doing a property read, otherwise
24 // the interface could be created after the read attempt but before the
25 // match is created.
26 entityManagerIfacesAddedMatch = std::make_unique<sdbusplus::bus::match_t>(
27 bus,
28 sdbusplus::bus::match::rules::interfacesAdded() +
29 sdbusplus::bus::match::rules::sender(
30 "xyz.openbmc_project.EntityManager"),
31 std::bind(&ChassisManager::entityManagerIfaceAdded, this,
32 std::placeholders::_1));
33
34 initializeChassisList();
35
36 // Request the bus name before the analyze() function, which is the one that
37 // determines the brownout condition and sets the status d-bus property.
38 bus.request_name(managerBusName);
39
40 using namespace sdeventplus;
41 auto interval = std::chrono::milliseconds(1000);
42 timer = std::make_unique<utility::Timer<ClockId::Monotonic>>(
43 e, std::bind(&ChassisManager::analyze, this), interval);
Faisal Awada9ed0f382025-08-14 13:21:46 -050044 initChassisPowerMonitoring();
Faisal Awada348168b2025-07-08 11:23:02 -050045}
46
47void ChassisManager::entityManagerIfaceAdded(sdbusplus::message_t& msg)
48{
49 try
50 {
51 phosphor::power::chassis::Chassis* chassisMatchPtr = nullptr;
52 sdbusplus::message::object_path objPath;
53 std::map<std::string, std::map<std::string, util::DbusVariant>>
54 interfaces;
55 msg.read(objPath, interfaces);
56
57 std::string objPathStr = objPath;
58
59 auto itInterface = interfaces.find(supportedConfIntf);
60 if (itInterface != interfaces.cend())
61 {
62 lg2::info("InterfacesAdded supportedConfIntf- objPathStr= {OBJ}",
63 "OBJ", objPathStr);
64 auto myChassisId = getParentEMUniqueId(bus, objPathStr);
65 chassisMatchPtr = getMatchingChassisPtr(myChassisId);
66 if (chassisMatchPtr)
67 {
68 lg2::debug("InterfacesAdded for: {SUPPORTED_CONFIGURATION}",
69 "SUPPORTED_CONFIGURATION", supportedConfIntf);
Faisal Awada9ed0f382025-08-14 13:21:46 -050070 chassisMatchPtr->supportedConfigurationInterfaceAdded(
71 itInterface->second);
Faisal Awada348168b2025-07-08 11:23:02 -050072 }
73 }
74 itInterface = interfaces.find(IBMCFFPSInterface);
75 if (itInterface != interfaces.cend())
76 {
77 lg2::debug("InterfacesAdded IBMCFFPSInterface- objPathStr= {OBJ}",
78 "OBJ", objPathStr);
79 auto myChassisId = getParentEMUniqueId(bus, objPathStr);
80 chassisMatchPtr = getMatchingChassisPtr(myChassisId);
81 if (chassisMatchPtr)
82 {
83 lg2::info("InterfacesAdded for: {IBMCFFPSINTERFACE}",
84 "IBMCFFPSINTERFACE", IBMCFFPSInterface);
Faisal Awada9ed0f382025-08-14 13:21:46 -050085 chassisMatchPtr->psuInterfaceAdded(itInterface->second);
Faisal Awada348168b2025-07-08 11:23:02 -050086 }
87 }
88 if (chassisMatchPtr != nullptr)
89 {
90 lg2::debug(
91 "InterfacesAdded validatePsuConfigAndInterfacesProcessed()");
Faisal Awada9ed0f382025-08-14 13:21:46 -050092 chassisMatchPtr->validatePsuConfigAndInterfacesProcessed();
Faisal Awada348168b2025-07-08 11:23:02 -050093 }
94 }
95 catch (const std::exception& e)
96 {
97 // Ignore, the property may be of a different type than expected.
98 }
99}
100
101phosphor::power::chassis::Chassis* ChassisManager::getMatchingChassisPtr(
102 uint64_t chassisId)
103{
104 for (const auto& chassisPtr : listOfChassis)
105 {
106 if (chassisPtr->getChassisId() == chassisId)
107 {
108 return chassisPtr.get();
109 }
110 }
111 lg2::debug("Chassis ID {ID} not found", "ID", chassisId);
112 return nullptr;
113}
114
115void ChassisManager::analyze()
116{
117 for (const auto& chassis : listOfChassis)
118 {
119 chassis->analyze();
120 }
121}
122
123void ChassisManager::initializeChassisList()
124{
125 try
126 {
127 auto chassisPathList = getChassisInventoryPaths(bus);
128 for (const auto& chassisPath : chassisPathList)
129 {
130 lg2::info(
131 "ChassisManager::initializeChassisList chassisPath= {CHASSIS_PATH}",
132 "CHASSIS_PATH", chassisPath);
133 auto chassis = std::make_unique<phosphor::power::chassis::Chassis>(
134 bus, chassisPath, eventLoop);
135 listOfChassis.push_back(std::move(chassis));
136 }
137 }
138 catch (const sdbusplus::exception_t& e)
139 {
140 lg2::error("Failed to initialize chassis list, error: {ERROR}", "ERROR",
141 e);
142 }
143}
Faisal Awada9ed0f382025-08-14 13:21:46 -0500144
145void ChassisManager::initChassisPowerMonitoring()
146{
147 for (const auto& chassis : listOfChassis)
148 {
149 chassis->initPowerMonitoring();
150 }
151}
152
Faisal Awada348168b2025-07-08 11:23:02 -0500153} // namespace phosphor::power::chassis_manager