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