xref: /openbmc/openpower-occ-control/occ_manager.hpp (revision b5ca101530dc5fa0992d00ab36edb292519cef94)
1 #pragma once
2 
3 #include "occ_pass_through.hpp"
4 #include "occ_status.hpp"
5 #ifdef PLDM
6 #include "pldm.hpp"
7 #endif
8 #include "powercap.hpp"
9 #include "utils.hpp"
10 #ifdef POWER10
11 #include "powermode.hpp"
12 #endif
13 
14 #include <sdbusplus/bus.hpp>
15 #include <sdeventplus/event.hpp>
16 #include <sdeventplus/utility/timer.hpp>
17 
18 #include <cstring>
19 #include <functional>
20 #include <vector>
21 
22 namespace sdbusRule = sdbusplus::bus::match::rules;
23 namespace open_power
24 {
25 namespace occ
26 {
27 
28 #ifdef READ_OCC_SENSORS
29 enum occFruType
30 {
31     processorCore = 0,
32     internalMemCtlr = 1,
33     dimm = 2,
34     memCtrlAndDimm = 3,
35     VRMVdd = 6,
36     PMIC = 7,
37     memCtlrExSensor = 8
38 };
39 #endif
40 
41 /** @brief Default time, in seconds, between OCC poll commands */
42 constexpr unsigned int defaultPollingInterval = 1;
43 
44 /** @class Manager
45  *  @brief Builds and manages OCC objects
46  */
47 struct Manager
48 {
49   public:
50     Manager() = delete;
51     Manager(const Manager&) = delete;
52     Manager& operator=(const Manager&) = delete;
53     Manager(Manager&&) = delete;
54     Manager& operator=(Manager&&) = delete;
55     ~Manager() = default;
56 
57     /** @brief Adds OCC pass-through and status objects on the bus
58      *         when corresponding CPU inventory is created.
59      *
60      *  @param[in] event - Unique ptr reference to sd_event
61      */
62     Manager(EventPtr& event) :
63         event(event), pollInterval(defaultPollingInterval),
64         sdpEvent(sdeventplus::Event::get_default()),
65         _pollTimer(
66             std::make_unique<
67                 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>(
68                 sdpEvent, std::bind(&Manager::pollerTimerExpired, this)))
69 #ifdef PLDM
70         ,
71         pldmHandle(std::make_unique<pldm::Interface>(
72             std::bind(std::mem_fn(&Manager::updateOCCActive), this,
73                       std::placeholders::_1, std::placeholders::_2)))
74 #endif
75 #ifdef POWER10
76         ,
77         discoverTimer(
78             std::make_unique<
79                 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>(
80                 sdpEvent, std::bind(&Manager::findAndCreateObjects, this)))
81 #endif
82     {
83 #ifdef I2C_OCC
84         // I2C OCC status objects are initialized directly
85         initStatusObjects();
86 #else
87         findAndCreateObjects();
88 #endif
89     }
90 
91     /** @brief Return the number of bound OCCs */
92     inline auto getNumOCCs() const
93     {
94         return activeCount;
95     }
96 
97   private:
98     /** @brief Creates the OCC D-Bus objects.
99      */
100     void findAndCreateObjects();
101 
102     /** @brief Callback that responds to cpu creation in the inventory -
103      *         by creating the needed objects.
104      *
105      *  @param[in] msg - bus message
106      *
107      *  @returns 0 to indicate success
108      */
109     int cpuCreated(sdbusplus::message::message& msg);
110 
111     /** @brief Create child OCC objects.
112      *
113      *  @param[in] occ - the occ name, such as occ0.
114      */
115     void createObjects(const std::string& occ);
116 
117     /** @brief Callback handler invoked by Status object when the OccActive
118      *         property is changed. This is needed to make sure that the
119      *         error detection is started only after all the OCCs are bound.
120      *         Similarly, when one of the OCC gets its OccActive property
121      *         un-set, then the OCC error detection needs to be stopped on
122      *         all the OCCs
123      *
124      *  @param[in] status - OccActive status
125      */
126     void statusCallBack(bool status);
127 
128     /** @brief Sends a Heartbeat command to host control command handler */
129     void sendHeartBeat();
130 
131     /** @brief reference to sd_event wrapped in unique_ptr */
132     EventPtr& event;
133 
134     /** @brief OCC pass-through objects */
135     std::vector<std::unique_ptr<PassThrough>> passThroughObjects;
136 
137     /** @brief OCC Status objects */
138     std::vector<std::unique_ptr<Status>> statusObjects;
139 
140     /** @brief Power cap monitor and occ notification object */
141     std::unique_ptr<open_power::occ::powercap::PowerCap> pcap;
142 
143 #ifdef POWER10
144     /** @brief Power mode monitor and notification object */
145     std::unique_ptr<open_power::occ::powermode::PowerMode> pmode;
146 #endif
147 
148     /** @brief sbdbusplus match objects */
149     std::vector<sdbusplus::bus::match_t> cpuMatches;
150 
151     /** @brief Number of OCCs that are bound */
152     uint8_t activeCount = 0;
153 
154     /** @brief Number of seconds between poll commands */
155     uint8_t pollInterval;
156 
157     /** @brief Poll timer event */
158     sdeventplus::Event sdpEvent;
159 
160     /**
161      * @brief The timer to be used once the OCC goes active.  When it expires,
162      *        a POLL command will be sent to the OCC and then timer restarted.
163      */
164     std::unique_ptr<
165         sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>
166         _pollTimer;
167 
168 #ifdef I2C_OCC
169     /** @brief Init Status objects for I2C OCC devices
170      *
171      * It iterates in /sys/bus/i2c/devices, finds all occ hwmon devices
172      * and creates status objects.
173      */
174     void initStatusObjects();
175 #endif
176 
177 #ifdef PLDM
178     /** @brief Callback handler invoked by the PLDM event handler when state of
179      *         the OCC is toggled by the host. The caller passes the instance
180      *         of the OCC and state of the OCC.
181      *
182      *  @param[in] instance - instance of the OCC
183      *  @param[in] status - true when the OCC goes active and false when the OCC
184      *                      goes inactive
185      *
186      *  @return true if setting the state of OCC is successful and false if it
187      *          fails.
188      */
189     bool updateOCCActive(instanceID instance, bool status);
190 
191     std::unique_ptr<pldm::Interface> pldmHandle = nullptr;
192 #endif
193 
194 #ifdef POWER10
195     /**
196      * @brief Timer used when discovering OCCs in /dev.
197      */
198     std::unique_ptr<
199         sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>
200         discoverTimer;
201 
202     /**
203      * @brief Used when discovering /dev/occ objects to know if
204      *        any were added since the last check.
205      */
206     std::vector<int> prevOCCSearch;
207 #endif
208 
209     /**
210      * @brief Called when poll timer expires and forces a POLL command to the
211      * OCC. The poll timer will then be restarted.
212      * */
213     void pollerTimerExpired();
214 
215     /**
216      * @brief Finds the OCC devices in /dev
217      *
218      * @return The IDs of the OCCs - 0, 1, etc.
219      */
220     std::vector<int> findOCCsInDev();
221 
222 #ifdef READ_OCC_SENSORS
223     /**
224      * @brief Gets the occ sensor values.
225      * @param[in] id - Id of the OCC.
226      * @param[in] masterOcc - Is this OCC the master OCC.
227      * */
228     void getSensorValues(uint32_t id, bool masterOcc);
229 
230     /**
231      * @brief Trigger OCC driver to read the temperature sensors.
232      * @param[in] path - path of the OCC sensors.
233      * @param[in] id - Id of the OCC.
234      * */
235     void readTempSensors(const fs::path& path, uint32_t id);
236 
237     /**
238      * @brief Trigger OCC driver to read the power sensors.
239      * @param[in] path - path of the OCC sensors.
240      * @param[in] id - Id of the OCC.
241      * */
242     void readPowerSensors(const fs::path& path, uint32_t id);
243 
244     /**
245      * @brief Set all sensor values of this OCC to NaN.
246      * @param[in] id - Id of the OCC.
247      * */
248     void setSensorValueToNaN(uint32_t id);
249 
250     /** @brief Store the existing OCC sensors on D-BUS */
251     std::map<std::string, uint32_t> existingSensors;
252 
253     /** @brief Get FunctionID from the `powerX_label` file.
254      *  @param[in] value - the value of the `powerX_label` file.
255      *  @returns FunctionID of the power sensors.
256      */
257     std::optional<std::string>
258         getPowerLabelFunctionID(const std::string& value);
259 
260     /** @brief The power sensor names map */
261     const std::map<std::string, std::string> powerSensorName = {
262         {"system", "total_power"}, {"1", "p0_mem_power"},
263         {"2", "p1_mem_power"},     {"3", "p2_mem_power"},
264         {"4", "p3_mem_power"},     {"5", "p0_power"},
265         {"6", "p1_power"},         {"7", "p2_power"},
266         {"8", "p3_power"},         {"9", "p0_cache_power"},
267         {"10", "p1_cache_power"},  {"11", "p2_cache_power"},
268         {"12", "p3_cache_power"},  {"13", "io_a_power"},
269         {"14", "io_b_power"},      {"15", "io_c_power"},
270         {"16", "fans_a_power"},    {"17", "fans_b_power"},
271         {"18", "storage_a_power"}, {"19", "storage_b_power"},
272         {"23", "mem_cache_power"}, {"25", "p0_mem_0_power"},
273         {"26", "p0_mem_1_power"},  {"27", "p0_mem_2_power"}};
274 
275     /** @brief The dimm temperature sensor names map */
276     const std::map<uint32_t, std::string> dimmTempSensorName = {
277         {internalMemCtlr, "_intmb_temp"},
278         {dimm, "_dram_temp"},
279         {memCtrlAndDimm, "_dram_extmb_temp"},
280         {PMIC, "_pmic_temp"},
281         {memCtlrExSensor, "_extmb_temp"}};
282 #endif
283 };
284 
285 } // namespace occ
286 } // namespace open_power
287