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