xref: /openbmc/phosphor-power/phosphor-power-supply/chassis_manager.cpp (revision 9ed0f38e1d59564106c6020b854416ece6753776)
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