blob: 9a29b8fb0d8c51e6d9d1fe308631b8b1919cd786 [file] [log] [blame]
Vishwanatha Subbanna2180b2d2017-06-28 14:05:57 +05301#pragma once
2
Vishwanatha Subbanna2180b2d2017-06-28 14:05:57 +05303#include "occ_pass_through.hpp"
Vishwanatha Subbanna307d80b2017-06-28 15:56:09 +05304#include "occ_status.hpp"
Tom Joseph815f9f52020-07-27 12:12:13 +05305#ifdef PLDM
6#include "pldm.hpp"
Eddie Jamescbad2192021-10-07 09:39:39 -05007
8#include <libphal.H>
Tom Joseph815f9f52020-07-27 12:12:13 +05309#endif
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +053010#include "powercap.hpp"
George Liuf3b75142021-06-10 11:22:50 +080011#include "utils.hpp"
Chris Cain78e86012021-03-04 16:15:31 -060012#ifdef POWER10
13#include "powermode.hpp"
14#endif
Vishwanatha Subbanna2180b2d2017-06-28 14:05:57 +053015
Gunnar Mills94df8c92018-09-14 14:50:03 -050016#include <sdbusplus/bus.hpp>
Chris Caina8857c52021-01-27 11:53:05 -060017#include <sdeventplus/event.hpp>
18#include <sdeventplus/utility/timer.hpp>
George Liub5ca1012021-09-10 12:53:11 +080019
20#include <cstring>
21#include <functional>
Gunnar Mills94df8c92018-09-14 14:50:03 -050022#include <vector>
23
Vishwanatha Subbanna2180b2d2017-06-28 14:05:57 +053024namespace sdbusRule = sdbusplus::bus::match::rules;
Vishwanatha Subbanna2180b2d2017-06-28 14:05:57 +053025namespace open_power
26{
27namespace occ
28{
29
Chicago Duanbb895cb2021-06-18 19:37:16 +080030#ifdef READ_OCC_SENSORS
31enum occFruType
32{
33 processorCore = 0,
34 internalMemCtlr = 1,
35 dimm = 2,
36 memCtrlAndDimm = 3,
37 VRMVdd = 6,
38 PMIC = 7,
Matt Spinlerace67d82021-10-18 13:41:57 -050039 memCtlrExSensor = 8,
40 processorIoRing = 9
Chicago Duanbb895cb2021-06-18 19:37:16 +080041};
42#endif
43
Chris Caina8857c52021-01-27 11:53:05 -060044/** @brief Default time, in seconds, between OCC poll commands */
Matt Spinler37923462021-09-24 11:38:05 -050045#ifndef POWER10
Chicago Duanbb895cb2021-06-18 19:37:16 +080046constexpr unsigned int defaultPollingInterval = 1;
Matt Spinler37923462021-09-24 11:38:05 -050047#else
48constexpr unsigned int defaultPollingInterval = 5;
49#endif
Chris Caina8857c52021-01-27 11:53:05 -060050
Chris Cain17257672021-10-22 13:41:03 -050051constexpr auto AMBIENT_PATH =
52 "/xyz/openbmc_project/sensors/temperature/Ambient_Virtual_Temp";
53constexpr auto AMBIENT_INTERFACE = "xyz.openbmc_project.Sensor.Value";
54constexpr auto AMBIENT_PROP = "Value";
55constexpr auto ALTITUDE_PATH = "/xyz/openbmc_project/sensors/altitude/Altitude";
56constexpr auto ALTITUDE_INTERFACE = "xyz.openbmc_project.Sensor.Value";
57constexpr auto ALTITUDE_PROP = "Value";
58
Vishwanatha Subbanna2180b2d2017-06-28 14:05:57 +053059/** @class Manager
60 * @brief Builds and manages OCC objects
61 */
62struct Manager
63{
Gunnar Mills94df8c92018-09-14 14:50:03 -050064 public:
65 Manager() = delete;
66 Manager(const Manager&) = delete;
67 Manager& operator=(const Manager&) = delete;
68 Manager(Manager&&) = delete;
69 Manager& operator=(Manager&&) = delete;
70 ~Manager() = default;
Vishwanatha Subbanna2180b2d2017-06-28 14:05:57 +053071
Gunnar Mills94df8c92018-09-14 14:50:03 -050072 /** @brief Adds OCC pass-through and status objects on the bus
73 * when corresponding CPU inventory is created.
74 *
Gunnar Mills94df8c92018-09-14 14:50:03 -050075 * @param[in] event - Unique ptr reference to sd_event
76 */
George Liuf3a4a692021-12-28 13:59:51 +080077 explicit Manager(EventPtr& event) :
George Liuf3b75142021-06-10 11:22:50 +080078 event(event), pollInterval(defaultPollingInterval),
Chris Caina8857c52021-01-27 11:53:05 -060079 sdpEvent(sdeventplus::Event::get_default()),
80 _pollTimer(
81 std::make_unique<
82 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>(
Chris Cain17257672021-10-22 13:41:03 -050083 sdpEvent, std::bind(&Manager::pollerTimerExpired, this))),
84 ambientPropChanged(
85 utils::getBus(),
86 sdbusRule::member("PropertiesChanged") +
87 sdbusRule::path(AMBIENT_PATH) +
88 sdbusRule::argN(0, AMBIENT_INTERFACE) +
89 sdbusRule::interface("org.freedesktop.DBus.Properties"),
90 std::bind(&Manager::ambientCallback, this, std::placeholders::_1))
Tom Joseph815f9f52020-07-27 12:12:13 +053091#ifdef PLDM
92 ,
93 pldmHandle(std::make_unique<pldm::Interface>(
George Liuf3b75142021-06-10 11:22:50 +080094 std::bind(std::mem_fn(&Manager::updateOCCActive), this,
Eddie Jamescbad2192021-10-07 09:39:39 -050095 std::placeholders::_1, std::placeholders::_2),
96 std::bind(std::mem_fn(&Manager::sbeHRESETResult), this,
George Liuf3b75142021-06-10 11:22:50 +080097 std::placeholders::_1, std::placeholders::_2)))
Tom Joseph815f9f52020-07-27 12:12:13 +053098#endif
Matt Spinlerd267cec2021-09-01 14:49:19 -050099#ifdef POWER10
100 ,
101 discoverTimer(
102 std::make_unique<
103 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>(
Chris Caina7b74dc2021-11-10 17:03:43 -0600104 sdpEvent, std::bind(&Manager::findAndCreateObjects, this))),
105 waitForAllOccsTimer(
106 std::make_unique<
107 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>(
108 sdpEvent, std::bind(&Manager::occsNotAllRunning, this)))
Matt Spinlerd267cec2021-09-01 14:49:19 -0500109#endif
Gunnar Mills94df8c92018-09-14 14:50:03 -0500110 {
Lei YU0ab90ca2017-07-13 17:02:23 +0800111#ifdef I2C_OCC
Gunnar Mills94df8c92018-09-14 14:50:03 -0500112 // I2C OCC status objects are initialized directly
113 initStatusObjects();
Lei YU0ab90ca2017-07-13 17:02:23 +0800114#else
Gunnar Mills94df8c92018-09-14 14:50:03 -0500115 findAndCreateObjects();
Lei YU0ab90ca2017-07-13 17:02:23 +0800116#endif
Chris Cain17257672021-10-22 13:41:03 -0500117 readAltitude();
Gunnar Mills94df8c92018-09-14 14:50:03 -0500118 }
Vishwanatha Subbanna2180b2d2017-06-28 14:05:57 +0530119
Chris Caina8857c52021-01-27 11:53:05 -0600120 /** @brief Return the number of bound OCCs */
Gunnar Mills94df8c92018-09-14 14:50:03 -0500121 inline auto getNumOCCs() const
122 {
123 return activeCount;
124 }
Edward A. James636577f2017-10-06 10:53:55 -0500125
Eddie Jamescbad2192021-10-07 09:39:39 -0500126#ifdef PLDM
127 /** @brief Called by a Device to report that the SBE timed out
128 * and appropriate action should be taken
129 *
130 * @param[in] instance - the OCC instance id
131 */
132 void sbeTimeout(unsigned int instance);
133#endif
134
Chris Cain17257672021-10-22 13:41:03 -0500135 /** @brief Return the latest ambient and altitude readings
136 *
137 * @param[out] ambientValid - true if ambientTemp is valid
138 * @param[out] ambient - ambient temperature in degrees C
139 * @param[out] altitude - altitude in meters
140 */
141 void getAmbientData(bool& ambientValid, uint8_t& ambientTemp,
142 uint16_t& altitude) const;
143
Gunnar Mills94df8c92018-09-14 14:50:03 -0500144 private:
Matt Spinlerd267cec2021-09-01 14:49:19 -0500145 /** @brief Creates the OCC D-Bus objects.
Gunnar Mills94df8c92018-09-14 14:50:03 -0500146 */
147 void findAndCreateObjects();
Vishwanatha Subbannadfc7ec72017-09-07 18:18:01 +0530148
Gunnar Mills94df8c92018-09-14 14:50:03 -0500149 /** @brief Callback that responds to cpu creation in the inventory -
150 * by creating the needed objects.
151 *
152 * @param[in] msg - bus message
153 *
154 * @returns 0 to indicate success
155 */
156 int cpuCreated(sdbusplus::message::message& msg);
Deepak Kodihalli5f031f32017-07-26 08:25:59 -0500157
Gunnar Mills94df8c92018-09-14 14:50:03 -0500158 /** @brief Create child OCC objects.
159 *
160 * @param[in] occ - the occ name, such as occ0.
161 */
162 void createObjects(const std::string& occ);
Vishwanatha Subbanna2180b2d2017-06-28 14:05:57 +0530163
Gunnar Mills94df8c92018-09-14 14:50:03 -0500164 /** @brief Callback handler invoked by Status object when the OccActive
165 * property is changed. This is needed to make sure that the
166 * error detection is started only after all the OCCs are bound.
167 * Similarly, when one of the OCC gets its OccActive property
168 * un-set, then the OCC error detection needs to be stopped on
169 * all the OCCs
170 *
171 * @param[in] status - OccActive status
172 */
173 void statusCallBack(bool status);
Vishwanatha Subbanna2dc9b1a2017-08-18 18:29:41 +0530174
Gunnar Mills94df8c92018-09-14 14:50:03 -0500175 /** @brief Sends a Heartbeat command to host control command handler */
176 void sendHeartBeat();
Vishwanatha Subbanna2dc9b1a2017-08-18 18:29:41 +0530177
Gunnar Mills94df8c92018-09-14 14:50:03 -0500178 /** @brief reference to sd_event wrapped in unique_ptr */
179 EventPtr& event;
Vishwanatha Subbannaee4d83d2017-06-29 18:35:00 +0530180
Gunnar Mills94df8c92018-09-14 14:50:03 -0500181 /** @brief OCC pass-through objects */
182 std::vector<std::unique_ptr<PassThrough>> passThroughObjects;
Vishwanatha Subbanna307d80b2017-06-28 15:56:09 +0530183
Gunnar Mills94df8c92018-09-14 14:50:03 -0500184 /** @brief OCC Status objects */
185 std::vector<std::unique_ptr<Status>> statusObjects;
Vishwanatha Subbanna2180b2d2017-06-28 14:05:57 +0530186
Gunnar Mills94df8c92018-09-14 14:50:03 -0500187 /** @brief Power cap monitor and occ notification object */
188 std::unique_ptr<open_power::occ::powercap::PowerCap> pcap;
Andrew Geissler52cf26a2017-07-06 12:56:32 -0500189
Chris Cain78e86012021-03-04 16:15:31 -0600190#ifdef POWER10
191 /** @brief Power mode monitor and notification object */
192 std::unique_ptr<open_power::occ::powermode::PowerMode> pmode;
193#endif
194
Gunnar Mills94df8c92018-09-14 14:50:03 -0500195 /** @brief sbdbusplus match objects */
196 std::vector<sdbusplus::bus::match_t> cpuMatches;
Vishwanatha Subbanna2dc9b1a2017-08-18 18:29:41 +0530197
Gunnar Mills94df8c92018-09-14 14:50:03 -0500198 /** @brief Number of OCCs that are bound */
199 uint8_t activeCount = 0;
Lei YU0ab90ca2017-07-13 17:02:23 +0800200
Chris Caina8857c52021-01-27 11:53:05 -0600201 /** @brief Number of seconds between poll commands */
202 uint8_t pollInterval;
203
Chris Cain17257672021-10-22 13:41:03 -0500204 /** @brief Ambient temperature of the system in degrees C */
205 uint8_t ambient = 0xFF; // default: not available
206
207 /** @brief Altitude of the system in meters */
208 uint16_t altitude = 0xFFFF; // default: not available
209
Chris Caina8857c52021-01-27 11:53:05 -0600210 /** @brief Poll timer event */
211 sdeventplus::Event sdpEvent;
212
213 /**
214 * @brief The timer to be used once the OCC goes active. When it expires,
215 * a POLL command will be sent to the OCC and then timer restarted.
216 */
217 std::unique_ptr<
218 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>
219 _pollTimer;
220
Chris Cain17257672021-10-22 13:41:03 -0500221 /** @brief Subscribe to ambient temperature changed events */
222 sdbusplus::bus::match_t ambientPropChanged;
223
Lei YU0ab90ca2017-07-13 17:02:23 +0800224#ifdef I2C_OCC
Gunnar Mills94df8c92018-09-14 14:50:03 -0500225 /** @brief Init Status objects for I2C OCC devices
226 *
227 * It iterates in /sys/bus/i2c/devices, finds all occ hwmon devices
228 * and creates status objects.
229 */
230 void initStatusObjects();
Lei YU0ab90ca2017-07-13 17:02:23 +0800231#endif
Tom Joseph815f9f52020-07-27 12:12:13 +0530232
233#ifdef PLDM
234 /** @brief Callback handler invoked by the PLDM event handler when state of
235 * the OCC is toggled by the host. The caller passes the instance
236 * of the OCC and state of the OCC.
237 *
238 * @param[in] instance - instance of the OCC
239 * @param[in] status - true when the OCC goes active and false when the OCC
240 * goes inactive
241 *
242 * @return true if setting the state of OCC is successful and false if it
243 * fails.
244 */
245 bool updateOCCActive(instanceID instance, bool status);
246
Eddie Jamescbad2192021-10-07 09:39:39 -0500247 /** @brief Callback handler invoked by PLDM sensor change when
248 * the HRESET succeeds or fails.
249 *
250 * @param[in] instance - the SBE instance id
251 * @param[in] success - true if the HRESET succeeded, otherwise false
252 */
253 void sbeHRESETResult(instanceID instance, bool success);
254
255 /** @brief Helper function to check whether an SBE dump should be collected
256 * now.
257 *
258 * @param[in] instance - the SBE instance id
259 *
260 * @return true if an SBE dump should be collected and false if not
261 */
262 bool sbeCanDump(unsigned int instance);
263
264 /** @brief Helper function to set the SBE state through PDBG/PHAL
265 *
266 * @param[in] instance - instance of the SBE
267 * @param[in] state - the state to which the SBE should be set
268 *
269 */
270 void setSBEState(unsigned int instance, enum sbe_state state);
271
272 /** @brief Helper function to get the SBE instance PDBG processor target
273 *
274 * @param[in] instance - the SBE instance id
275 *
276 * @return a pointer to the PDBG target
277 */
278 struct pdbg_target* getPdbgTarget(unsigned int instance);
279
280 /** @brief Whether pdbg_targets_init has been called */
281 bool pdbgInitialized = false;
282
Tom Joseph815f9f52020-07-27 12:12:13 +0530283 std::unique_ptr<pldm::Interface> pldmHandle = nullptr;
284#endif
Chris Caina8857c52021-01-27 11:53:05 -0600285
Matt Spinlerd267cec2021-09-01 14:49:19 -0500286#ifdef POWER10
287 /**
288 * @brief Timer used when discovering OCCs in /dev.
289 */
290 std::unique_ptr<
291 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>
292 discoverTimer;
293
294 /**
295 * @brief Used when discovering /dev/occ objects to know if
296 * any were added since the last check.
297 */
298 std::vector<int> prevOCCSearch;
Chris Caina7b74dc2021-11-10 17:03:43 -0600299
300 /**
301 * @brief Timer used when waiting for OCCs to go active.
302 */
303 std::unique_ptr<
304 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>
305 waitForAllOccsTimer;
306
307 /** @brief Called when code times out waiting for all OCCs to be running or
308 * after the app is restarted (Status does not callback into
309 * Manager).
310 */
311 void occsNotAllRunning();
Matt Spinlerd267cec2021-09-01 14:49:19 -0500312#endif
313
Chris Caina8857c52021-01-27 11:53:05 -0600314 /**
315 * @brief Called when poll timer expires and forces a POLL command to the
316 * OCC. The poll timer will then be restarted.
317 * */
318 void pollerTimerExpired();
Chicago Duanbb895cb2021-06-18 19:37:16 +0800319
Matt Spinlerd267cec2021-09-01 14:49:19 -0500320 /**
321 * @brief Finds the OCC devices in /dev
322 *
323 * @return The IDs of the OCCs - 0, 1, etc.
324 */
325 std::vector<int> findOCCsInDev();
326
Chicago Duanbb895cb2021-06-18 19:37:16 +0800327#ifdef READ_OCC_SENSORS
328 /**
329 * @brief Gets the occ sensor values.
330 * @param[in] id - Id of the OCC.
331 * @param[in] masterOcc - Is this OCC the master OCC.
332 * */
333 void getSensorValues(uint32_t id, bool masterOcc);
334
335 /**
336 * @brief Trigger OCC driver to read the temperature sensors.
337 * @param[in] path - path of the OCC sensors.
338 * @param[in] id - Id of the OCC.
339 * */
340 void readTempSensors(const fs::path& path, uint32_t id);
341
342 /**
343 * @brief Trigger OCC driver to read the power sensors.
344 * @param[in] path - path of the OCC sensors.
345 * @param[in] id - Id of the OCC.
346 * */
347 void readPowerSensors(const fs::path& path, uint32_t id);
348
349 /**
350 * @brief Set all sensor values of this OCC to NaN.
351 * @param[in] id - Id of the OCC.
352 * */
353 void setSensorValueToNaN(uint32_t id);
354
355 /** @brief Store the existing OCC sensors on D-BUS */
356 std::map<std::string, uint32_t> existingSensors;
357
358 /** @brief Get FunctionID from the `powerX_label` file.
359 * @param[in] value - the value of the `powerX_label` file.
360 * @returns FunctionID of the power sensors.
361 */
362 std::optional<std::string>
363 getPowerLabelFunctionID(const std::string& value);
364
365 /** @brief The power sensor names map */
366 const std::map<std::string, std::string> powerSensorName = {
367 {"system", "total_power"}, {"1", "p0_mem_power"},
368 {"2", "p1_mem_power"}, {"3", "p2_mem_power"},
369 {"4", "p3_mem_power"}, {"5", "p0_power"},
370 {"6", "p1_power"}, {"7", "p2_power"},
371 {"8", "p3_power"}, {"9", "p0_cache_power"},
372 {"10", "p1_cache_power"}, {"11", "p2_cache_power"},
373 {"12", "p3_cache_power"}, {"13", "io_a_power"},
374 {"14", "io_b_power"}, {"15", "io_c_power"},
375 {"16", "fans_a_power"}, {"17", "fans_b_power"},
376 {"18", "storage_a_power"}, {"19", "storage_b_power"},
377 {"23", "mem_cache_power"}, {"25", "p0_mem_0_power"},
378 {"26", "p0_mem_1_power"}, {"27", "p0_mem_2_power"}};
379
380 /** @brief The dimm temperature sensor names map */
381 const std::map<uint32_t, std::string> dimmTempSensorName = {
382 {internalMemCtlr, "_intmb_temp"},
383 {dimm, "_dram_temp"},
384 {memCtrlAndDimm, "_dram_extmb_temp"},
385 {PMIC, "_pmic_temp"},
386 {memCtlrExSensor, "_extmb_temp"}};
387#endif
Chris Cain17257672021-10-22 13:41:03 -0500388
389 /** @brief Read the altitude from DBus */
390 void readAltitude();
391
392 /** @brief Callback function when ambient temperature changes
393 *
394 * @param[in] msg - Data associated with subscribed signal
395 */
396 void ambientCallback(sdbusplus::message::message& msg);
Chris Caina7b74dc2021-11-10 17:03:43 -0600397
398 /** @brief Confirm that a single OCC master was found and start presence
399 * monitoring
400 */
401 void validateOccMaster();
Vishwanatha Subbanna2180b2d2017-06-28 14:05:57 +0530402};
403
404} // namespace occ
405} // namespace open_power