1 #include "config.h"
2
3 #include "chassis_manager.hpp"
4
5 #include <phosphor-logging/lg2.hpp>
6
7 using namespace phosphor::logging;
8
9 namespace phosphor::power::chassis_manager
10 {
11 using namespace phosphor::power::util;
12 constexpr auto managerBusName =
13 "xyz.openbmc_project.Power.MultiChassisPSUMonitor";
14 constexpr auto IBMCFFPSInterface =
15 "xyz.openbmc_project.Configuration.IBMCFFPSConnector";
16 constexpr auto supportedConfIntf =
17 "xyz.openbmc_project.Configuration.SupportedConfiguration";
18
ChassisManager(sdbusplus::bus_t & bus,const sdeventplus::Event & e)19 ChassisManager::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);
44 initChassisPowerMonitoring();
45 }
46
entityManagerIfaceAdded(sdbusplus::message_t & msg)47 void 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);
70 chassisMatchPtr->supportedConfigurationInterfaceAdded(
71 itInterface->second);
72 }
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);
85 chassisMatchPtr->psuInterfaceAdded(itInterface->second);
86 }
87 }
88 if (chassisMatchPtr != nullptr)
89 {
90 lg2::debug(
91 "InterfacesAdded validatePsuConfigAndInterfacesProcessed()");
92 chassisMatchPtr->validatePsuConfigAndInterfacesProcessed();
93 }
94 }
95 catch (const std::exception& e)
96 {
97 // Ignore, the property may be of a different type than expected.
98 }
99 }
100
getMatchingChassisPtr(uint64_t chassisId)101 phosphor::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
analyze()115 void ChassisManager::analyze()
116 {
117 for (const auto& chassis : listOfChassis)
118 {
119 chassis->analyze();
120 }
121 }
122
initializeChassisList()123 void 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 }
144
initChassisPowerMonitoring()145 void ChassisManager::initChassisPowerMonitoring()
146 {
147 for (const auto& chassis : listOfChassis)
148 {
149 chassis->initPowerMonitoring();
150 }
151 }
152
153 } // namespace phosphor::power::chassis_manager
154