blob: 606c65ea590cb61de676e0d8d90106773fa6952a [file] [log] [blame]
Vishwanatha Subbanna307d80b2017-06-28 15:56:09 +05301#pragma once
George Liubddcf852021-09-08 08:46:22 +08002#include "config.h"
Vishwanatha Subbanna307d80b2017-06-28 15:56:09 +05303
Chris Caina8857c52021-01-27 11:53:05 -06004#include "occ_command.hpp"
Gunnar Mills94df8c92018-09-14 14:50:03 -05005#include "occ_device.hpp"
6#include "occ_events.hpp"
Chris Cain5d66a0a2022-02-09 08:52:10 -06007#include "powercap.hpp"
Chris Cain36f9cde2021-11-22 11:18:21 -06008#include "powermode.hpp"
George Liuf3b75142021-06-10 11:22:50 +08009#include "utils.hpp"
Gunnar Mills94df8c92018-09-14 14:50:03 -050010
Gunnar Mills94df8c92018-09-14 14:50:03 -050011#include <org/open_power/Control/Host/server.hpp>
12#include <org/open_power/OCC/Status/server.hpp>
Vishwanatha Subbanna307d80b2017-06-28 15:56:09 +053013#include <sdbusplus/bus.hpp>
14#include <sdbusplus/server/object.hpp>
Chris Caina7b74dc2021-11-10 17:03:43 -060015#include <sdeventplus/event.hpp>
16#include <sdeventplus/utility/timer.hpp>
Chris Cainc86d80f2023-05-04 15:49:18 -050017#include <xyz/openbmc_project/Control/Power/Throttle/server.hpp>
Lei YU0ab90ca2017-07-13 17:02:23 +080018
George Liub5ca1012021-09-10 12:53:11 +080019#include <functional>
20
Vishwanatha Subbanna307d80b2017-06-28 15:56:09 +053021namespace open_power
22{
23namespace occ
24{
25
Edward A. James636577f2017-10-06 10:53:55 -050026class Manager;
Vishwanatha Subbanna307d80b2017-06-28 15:56:09 +053027namespace Base = sdbusplus::org::open_power::OCC::server;
Patrick Williamsaf408082022-07-22 19:26:54 -050028using Interface = sdbusplus::server::object_t<Base::Status>;
Vishwanatha Subbanna307d80b2017-06-28 15:56:09 +053029
Chris Cainc86d80f2023-05-04 15:49:18 -050030namespace xyzBase = sdbusplus::xyz::openbmc_project::Control::Power::server;
31using ThrottleInterface = sdbusplus::server::object_t<xyzBase::Throttle>;
32
Vishwanatha Subbanna30e329a2017-07-24 23:13:14 +053033// IPMID's host control application
34namespace Control = sdbusplus::org::open_power::Control::server;
35
36// For waiting on signals
37namespace sdbusRule = sdbusplus::bus::match::rules;
38
Vishwanatha Subbanna6add0b82017-07-21 19:02:37 +053039// OCC status instance. Ex. for "occ0", the instance is 0
Chris Cain7e374fb2022-04-07 09:47:23 -050040using instanceID = unsigned int;
Vishwanatha Subbanna6add0b82017-07-21 19:02:37 +053041
42// IPMI sensor ID for a given OCC instance
43using sensorID = uint8_t;
44
Alexander Filippov1d69e192019-03-21 18:12:07 +030045// Human readable sensor name for DBus tree. E.g. "CPU0_OCC"
46using sensorName = std::string;
47
48// OCC sensors definitions in the map
49using sensorDefs = std::tuple<sensorID, sensorName>;
50
Eddie Jamese7d976b2018-02-26 13:42:45 -060051// OCC sysfs name prefix
52const std::string sysfsName = "occ-hwmon";
53
Chris Cainc86d80f2023-05-04 15:49:18 -050054const uint8_t THROTTLED_NONE = 0x00;
55const uint8_t THROTTLED_POWER = 0x01;
56const uint8_t THROTTLED_THERMAL = 0x02;
57const uint8_t THROTTLED_SAFE = 0x04;
58const uint8_t THROTTLED_ALL = 0xFF;
59
Vishwanatha Subbanna307d80b2017-06-28 15:56:09 +053060/** @class Status
61 * @brief Implementation of OCC Active Status
62 */
63class Status : public Interface
64{
Gunnar Mills94df8c92018-09-14 14:50:03 -050065 public:
66 Status() = delete;
67 ~Status() = default;
68 Status(const Status&) = delete;
69 Status& operator=(const Status&) = delete;
70 Status(Status&&) = default;
71 Status& operator=(Status&&) = default;
Vishwanatha Subbanna307d80b2017-06-28 15:56:09 +053072
Gunnar Mills94df8c92018-09-14 14:50:03 -050073 /** @brief Constructs the Status object and
74 * the underlying device object
75 *
Gunnar Mills94df8c92018-09-14 14:50:03 -050076 * @param[in] event - sd_event unique pointer reference
77 * @param[in] path - DBus object path
78 * @param[in] manager - OCC manager instance
79 * @param[in] callBack - Callback handler to invoke during
80 * property change
Tom Joseph00325232020-07-29 17:51:48 +053081 * @param[in] resetCallBack - callback handler to invoke for resetting the
82 * OCC if PLDM is the host communication
83 * protocol
Gunnar Mills94df8c92018-09-14 14:50:03 -050084 */
Chris Cain17257672021-10-22 13:41:03 -050085 Status(EventPtr& event, const char* path, Manager& managerRef,
Chris Cain5d66a0a2022-02-09 08:52:10 -060086 std::unique_ptr<powermode::PowerMode>& powerModeRef,
Sheldon Bailey16a5adb2025-06-10 14:10:06 -050087 std::function<void(instanceID, bool)> callBack = nullptr,
88 std::function<void(instanceID)> resetCallBack = nullptr) :
Patrick Williams1923a752022-04-05 21:35:45 -050089 Interface(utils::getBus(), getDbusPath(path).c_str(),
90 Interface::action::defer_emit),
Chris Cain1be43372021-12-09 19:29:37 -060091 path(path), managerCallBack(callBack), instance(getInstance(path)),
Sheldon Bailey16a5adb2025-06-10 14:10:06 -050092 manager(managerRef), pmode(powerModeRef),
Gunnar Mills94df8c92018-09-14 14:50:03 -050093 device(event,
Eddie James774f9af2019-03-19 20:58:53 +000094 fs::path(DEV_PATH) /
95 fs::path(sysfsName + "." + std::to_string(instance + 1)),
Sheldon Bailey16a5adb2025-06-10 14:10:06 -050096 managerRef, *this, powerModeRef, instance),
Gunnar Mills94df8c92018-09-14 14:50:03 -050097 hostControlSignal(
George Liuf3b75142021-06-10 11:22:50 +080098 utils::getBus(),
Gunnar Mills94df8c92018-09-14 14:50:03 -050099 sdbusRule::type::signal() + sdbusRule::member("CommandComplete") +
100 sdbusRule::path("/org/open_power/control/host0") +
101 sdbusRule::interface("org.open_power.Control.Host") +
102 sdbusRule::argN(0, Control::convertForMessage(
103 Control::Host::Command::OCCReset)),
104 std::bind(std::mem_fn(&Status::hostControlEvent), this,
Chris Caina8857c52021-01-27 11:53:05 -0600105 std::placeholders::_1)),
George Liuf3b75142021-06-10 11:22:50 +0800106 occCmd(instance, (fs::path(OCC_CONTROL_ROOT) /
107 (std::string(OCC_NAME) + std::to_string(instance)))
Sheldon Bailey16a5adb2025-06-10 14:10:06 -0500108 .c_str()),
Chris Caina7b74dc2021-11-10 17:03:43 -0600109 sdpEvent(sdeventplus::Event::get_default()),
110 safeStateDelayTimer(
111 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>(
Sheldon Bailey16a5adb2025-06-10 14:10:06 -0500112 sdpEvent, std::bind(&Status::safeStateDelayExpired, this))),
Tom Joseph00325232020-07-29 17:51:48 +0530113 resetCallBack(resetCallBack)
Gunnar Mills94df8c92018-09-14 14:50:03 -0500114 {
Gunnar Mills94df8c92018-09-14 14:50:03 -0500115 // Announce that we are ready
116 this->emit_object_added();
117 }
Vishwanatha Subbanna32e84e92017-06-28 19:17:28 +0530118
Gunnar Mills94df8c92018-09-14 14:50:03 -0500119 /** @brief Since we are overriding the setter-occActive but not the
120 * getter-occActive, we need to have this using in order to
121 * allow passthrough usage of the getter-occActive
122 */
123 using Base::Status::occActive;
Vishwanatha Subbanna32e84e92017-06-28 19:17:28 +0530124
Gunnar Mills94df8c92018-09-14 14:50:03 -0500125 /** @brief SET OccActive to True or False
126 *
127 * @param[in] value - Intended value
128 *
129 * @return - Updated value of the property
130 */
131 bool occActive(bool value) override;
Vishwanatha Subbanna2dc9b1a2017-08-18 18:29:41 +0530132
Gunnar Mills94df8c92018-09-14 14:50:03 -0500133 /** @brief Starts OCC error detection */
134 inline void addErrorWatch()
135 {
136 return device.addErrorWatch();
137 }
Vishwanatha Subbanna2dc9b1a2017-08-18 18:29:41 +0530138
Gunnar Mills94df8c92018-09-14 14:50:03 -0500139 /** @brief Stops OCC error detection */
140 inline void removeErrorWatch()
141 {
142 return device.removeErrorWatch();
143 }
Eddie Jamesdae2d942017-12-20 10:50:03 -0600144
Gunnar Mills94df8c92018-09-14 14:50:03 -0500145 /** @brief Starts to watch how many OCCs are present on the master */
146 inline void addPresenceWatchMaster()
147 {
148 return device.addPresenceWatchMaster();
149 }
Vishwanatha Subbanna30e329a2017-07-24 23:13:14 +0530150
Chicago Duanbb895cb2021-06-18 19:37:16 +0800151 /** @brief Gets the occ instance number */
152 unsigned int getOccInstanceID()
153 {
154 return instance;
155 }
156
157 /** @brief Is this OCC the master OCC */
158 bool isMasterOcc()
159 {
160 return device.master();
161 }
162
Chris Caina8857c52021-01-27 11:53:05 -0600163 /** @brief Read OCC state (will trigger kernel to poll the OCC) */
164 void readOccState();
165
Eddie James9789e712022-05-25 15:43:40 -0500166 /** @brief Called when device errors are detected
167 *
168 * @param[in] d - description of the error that occurred
169 */
170 void deviceError(Error::Descriptor d = Error::Descriptor());
Eddie Jamescbad2192021-10-07 09:39:39 -0500171
Chris Cain78e86012021-03-04 16:15:31 -0600172 /** @brief Handle additional tasks when the OCCs reach active state */
173 void occsWentActive();
174
Chris Cain17257672021-10-22 13:41:03 -0500175 /** @brief Send Ambient & Altitude data to OCC
176 *
177 * @param[in] ambient - temperature to send (0xFF will force read
178 * of current temperature and altitude)
179 * @param[in] altitude - altitude to send (0xFFFF = unavailable)
180 *
181 * @return SUCCESS on success
182 */
183 CmdStatus sendAmbient(const uint8_t ambient = 0xFF,
184 const uint16_t altitude = 0xFFFF);
Chris Cain733b2012022-05-04 11:54:06 -0500185
186 /** @brief Set flag indicating if PLDM sensor has been received
187 *
188 * @param[in] wasReceived - true if PLDM sensor was read
189 */
190 void setPldmSensorReceived(const bool wasReceived)
191 {
192 pldmSensorStateReceived = wasReceived;
193 }
194
195 /** @brief Read flag indicating if PLDM sensor has been read
196 *
197 * @return true if sensor has been read
198 */
199 bool getPldmSensorReceived()
200 {
201 return pldmSensorStateReceived;
202 }
Chris Cain78e86012021-03-04 16:15:31 -0600203
Chris Cain5d66a0a2022-02-09 08:52:10 -0600204 /** @brief Return the HWMON path for this OCC
205 *
206 * @return path or empty path if not found
207 */
Chris Caine2d0a432022-03-28 11:08:49 -0500208 fs::path getHwmonPath();
Chris Cain5d66a0a2022-02-09 08:52:10 -0600209
Chris Cainc86d80f2023-05-04 15:49:18 -0500210 /** @brief Update the processor path associated with this OCC
211 */
212 void updateProcAssociation()
213 {
214 readProcAssociation();
215 if (nullptr != throttleHandle)
216 {
217 throttleHandle.reset();
218 }
219 if (!procPath.empty())
220 {
221 throttleHandle = std::make_unique<ThrottleInterface>(
222 utils::getBus(), procPath.c_str());
223 }
224 }
225
226 /** @brief Update the processor throttle status on dbus
227 */
228 void updateThrottle(const bool isThrottled, const uint8_t reason);
229
Gunnar Mills94df8c92018-09-14 14:50:03 -0500230 private:
Gunnar Mills94df8c92018-09-14 14:50:03 -0500231 /** @brief OCC dbus object path */
232 std::string path;
Vishwanatha Subbanna32e84e92017-06-28 19:17:28 +0530233
Chris Cainc86d80f2023-05-04 15:49:18 -0500234 /** @brief Processor path associated with this OCC */
235 std::string procPath;
236
Gunnar Mills94df8c92018-09-14 14:50:03 -0500237 /** @brief Callback handler to be invoked during property change.
238 * This is a handler in Manager class
239 */
Sheldon Bailey373af752022-02-21 15:14:00 -0600240 std::function<void(instanceID, bool)> managerCallBack;
Vishwanatha Subbanna2dc9b1a2017-08-18 18:29:41 +0530241
Gunnar Mills94df8c92018-09-14 14:50:03 -0500242 /** @brief OCC instance number. Ex, 0,1, etc */
Chris Caina8857c52021-01-27 11:53:05 -0600243 unsigned int instance;
244
245 /** @brief The last state read from the OCC */
246 unsigned int lastState = 0;
Vishwanatha Subbanna6add0b82017-07-21 19:02:37 +0530247
Chris Cainf0295f52024-09-12 15:41:14 -0500248 /** @brief The last OCC read status (0 = no error) */
249 int lastOccReadStatus = 0;
250
Sheldon Bailey373af752022-02-21 15:14:00 -0600251 /** @brief Number of retry attempts to open file and update state. */
252 const unsigned int occReadRetries = 1;
253
254 /** @brief Current number of retries attempted towards occReadRetries. */
255 size_t currentOccReadRetriesCount = 0;
256
257 /** @brief The Trigger to indicate OCC State is valid or not. */
258 bool stateValid = false;
259
Chris Cainf7881502025-04-16 14:48:30 -0500260 /** @brief The Trigger to indicate OCC sensors are valid or not. */
261 bool sensorsValid = false;
Chris Cainf7881502025-04-16 14:48:30 -0500262
Alexander Filippov1d69e192019-03-21 18:12:07 +0300263 /** @brief OCC instance to Sensor definitions mapping */
264 static const std::map<instanceID, sensorDefs> sensorMap;
Vishwanatha Subbanna6add0b82017-07-21 19:02:37 +0530265
Chris Cain17257672021-10-22 13:41:03 -0500266 /** @brief OCC manager object */
267 const Manager& manager;
268
Chris Cain36f9cde2021-11-22 11:18:21 -0600269 /** @brief OCC PowerMode object */
Chris Cain5d66a0a2022-02-09 08:52:10 -0600270 std::unique_ptr<powermode::PowerMode>& pmode;
Chris Cain36f9cde2021-11-22 11:18:21 -0600271
Gunnar Mills94df8c92018-09-14 14:50:03 -0500272 /** @brief OCC device object to do bind and unbind */
273 Device device;
Vishwanatha Subbannaee4d83d2017-06-29 18:35:00 +0530274
Gunnar Mills94df8c92018-09-14 14:50:03 -0500275 /** @brief Subscribe to host control signal
276 *
277 * Once the OCC reset is requested, BMC sends that message to host.
278 * If the host does not ack the message, then there would be a timeout
279 * and we need to catch that to log an error
280 **/
281 sdbusplus::bus::match_t hostControlSignal;
Vishwanatha Subbanna30e329a2017-07-24 23:13:14 +0530282
Chris Caina8857c52021-01-27 11:53:05 -0600283 /** @brief Command object to send commands to the OCC */
284 OccCommand occCmd;
285
Chris Caina7b74dc2021-11-10 17:03:43 -0600286 /** @brief timer event */
287 sdeventplus::Event sdpEvent;
Chris Caina7b74dc2021-11-10 17:03:43 -0600288
Chris Caine2d0a432022-03-28 11:08:49 -0500289 /** @brief hwmon path for this OCC */
290 fs::path hwmonPath;
291
Chris Cain733b2012022-05-04 11:54:06 -0500292 /** @brief flag indicating if the OCC sensor has been received */
293 bool pldmSensorStateReceived = false;
294
Gunnar Mills94df8c92018-09-14 14:50:03 -0500295 /** @brief Callback function on host control signals
296 *
297 * @param[in] msg - Data associated with subscribed signal
298 */
Patrick Williamsaf408082022-07-22 19:26:54 -0500299 void hostControlEvent(sdbusplus::message_t& msg);
Vishwanatha Subbanna30e329a2017-07-24 23:13:14 +0530300
Gunnar Mills94df8c92018-09-14 14:50:03 -0500301 /** @brief Sends a message to host control command handler to reset OCC
302 */
303 void resetOCC();
Alexander Filippov1d69e192019-03-21 18:12:07 +0300304
305 /** @brief Determines the instance ID by specified object path.
306 * @param[in] path Estimated OCC Dbus object path
307 * @return Instance number
308 */
309 static int getInstance(const std::string& path)
310 {
311 return (path.empty() ? 0 : path.back() - '0');
312 }
313
Chris Caina7b74dc2021-11-10 17:03:43 -0600314 /**
315 * @brief Timer that is started when OCC is detected to be in safe mode
316 */
317 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>
318 safeStateDelayTimer;
319
320 /** @brief Callback for timer that is started when OCC was detected to be in
321 * safe mode. Called to verify and then disable and reset the OCCs.
322 */
323 void safeStateDelayExpired();
Chris Cainf0295f52024-09-12 15:41:14 -0500324
Sheldon Bailey373af752022-02-21 15:14:00 -0600325 /** @brief Callback for timer that is started when OCC state
326 * was not able to be read. Called to attempt another read when needed.
327 */
328 void occReadStateNow();
Chris Cain78e86012021-03-04 16:15:31 -0600329
Alexander Filippov1d69e192019-03-21 18:12:07 +0300330 /** @brief Override the sensor name with name from the definition.
331 * @param[in] estimatedPath - Estimated OCC Dbus object path
332 * @return Fixed OCC DBus object path
333 */
334 static std::string getDbusPath(const std::string& estimatedPath)
335 {
336 if (!estimatedPath.empty())
337 {
338 auto it = sensorMap.find(getInstance(estimatedPath));
339 if (sensorMap.end() != it)
340 {
341 auto& name = std::get<1>(it->second);
342 if (!name.empty() && name != "None")
343 {
George Liuf3a4a692021-12-28 13:59:51 +0800344 auto objectPath = fs::path(estimatedPath);
345 objectPath.replace_filename(name);
346 return objectPath.string();
Alexander Filippov1d69e192019-03-21 18:12:07 +0300347 }
348 }
349 }
350
351 return estimatedPath;
352 }
Sheldon Bailey16a5adb2025-06-10 14:10:06 -0500353
Tom Joseph00325232020-07-29 17:51:48 +0530354 std::function<void(instanceID)> resetCallBack = nullptr;
Chris Cainc86d80f2023-05-04 15:49:18 -0500355
356 /** @brief Current throttle reason(s) for this processor */
357 uint8_t throttleCause = THROTTLED_NONE;
358
359 /** @brief Throttle interface for the processor associated with this OCC */
360 std::unique_ptr<ThrottleInterface> throttleHandle;
361
362 /** @brief Read the processor path associated with this OCC */
363 void readProcAssociation();
Vishwanatha Subbanna307d80b2017-06-28 15:56:09 +0530364};
365
366} // namespace occ
367} // namespace open_power