blob: d81cd5395616fa6a5809ffe2b97772df6e42dc02 [file] [log] [blame]
Patrick Ventured8012182018-03-08 08:21:38 -08001#pragma once
2
Patrick Ventureda4a5dd2018-08-31 09:42:48 -07003#include "conf.hpp"
4#include "controller.hpp"
James Zheng6df8bb52024-11-27 23:38:47 +00005#include "failsafeloggers/failsafe_logger_utility.hpp"
Ed Tanousf8b6e552025-06-27 13:27:50 -07006#include "interfaces.hpp"
James Feist22c257a2018-08-31 14:07:12 -07007#include "pidcontroller.hpp"
Patrick Ventureda4a5dd2018-08-31 09:42:48 -07008#include "sensors/manager.hpp"
9#include "sensors/sensor.hpp"
Patrick Venturec32e3fc2019-02-28 10:01:11 -080010#include "tuning.hpp"
Patrick Venture1a153792020-08-11 08:41:47 -070011#include "zone_interface.hpp"
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070012
Patrick Venturea83a3ec2020-08-04 09:52:05 -070013#include <sdbusplus/bus.hpp>
Ed Tanousf8b6e552025-06-27 13:27:50 -070014#include <sdbusplus/server/object.hpp>
Patrick Venturea83a3ec2020-08-04 09:52:05 -070015#include <xyz/openbmc_project/Control/Mode/server.hpp>
Harvey Wu37180062023-10-02 09:42:50 +080016#include <xyz/openbmc_project/Debug/Pid/ThermalPower/server.hpp>
Harvey Wucc0232a2023-02-09 14:58:55 +080017#include <xyz/openbmc_project/Debug/Pid/Zone/server.hpp>
ykchiu7c6d35d2023-05-10 17:01:46 +080018#include <xyz/openbmc_project/Object/Enable/server.hpp>
Patrick Venturea83a3ec2020-08-04 09:52:05 -070019
Ed Tanousf8b6e552025-06-27 13:27:50 -070020#include <chrono>
21#include <cstdint>
Patrick Ventured8012182018-03-08 08:21:38 -080022#include <fstream>
Tom Tungdf1f1832022-11-14 19:26:52 +080023#include <iostream>
Patrick Ventured8012182018-03-08 08:21:38 -080024#include <map>
25#include <memory>
26#include <set>
27#include <string>
Ed Tanousf8b6e552025-06-27 13:27:50 -070028#include <string_view>
29#include <utility>
Patrick Ventured8012182018-03-08 08:21:38 -080030#include <vector>
31
Patrick Ventured8012182018-03-08 08:21:38 -080032template <typename... T>
Patrick Williamsb228bc32022-07-22 19:26:56 -050033using ServerObject = typename sdbusplus::server::object_t<T...>;
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070034using ModeInterface = sdbusplus::xyz::openbmc_project::Control::server::Mode;
Harvey Wucc0232a2023-02-09 14:58:55 +080035using DebugZoneInterface =
36 sdbusplus::xyz::openbmc_project::Debug::Pid::server::Zone;
37using ModeObject = ServerObject<ModeInterface, DebugZoneInterface>;
ykchiu7c6d35d2023-05-10 17:01:46 +080038using ProcessInterface =
39 sdbusplus::xyz::openbmc_project::Object::server::Enable;
Harvey Wu37180062023-10-02 09:42:50 +080040using DebugThermalPowerInterface =
41 sdbusplus::xyz::openbmc_project::Debug::Pid::server::ThermalPower;
42using ProcessObject =
43 ServerObject<ProcessInterface, DebugThermalPowerInterface>;
Harvey Wua4270072024-05-29 16:11:13 +080044using FailSafeSensorsMap =
45 std::map<std::string, std::pair<std::string, double>>;
46using FailSafeSensorPair =
47 std::pair<std::string, std::pair<std::string, double>>;
Patrick Ventured8012182018-03-08 08:21:38 -080048
Patrick Venturea0764872020-08-08 07:48:43 -070049namespace pid_control
50{
51
Patrick Ventured8012182018-03-08 08:21:38 -080052/*
Patrick Venture597ebd62020-08-11 08:48:19 -070053 * The DbusPidZone inherits from the Mode object so that it can listen for
54 * control mode changes. It primarily holds all PID loops and holds the sensor
55 * value cache that's used per iteration of the PID loops.
Patrick Ventured8012182018-03-08 08:21:38 -080056 */
Patrick Venture597ebd62020-08-11 08:48:19 -070057class DbusPidZone : public ZoneInterface, public ModeObject
Patrick Ventured8012182018-03-08 08:21:38 -080058{
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070059 public:
Patrick Venture597ebd62020-08-11 08:48:19 -070060 DbusPidZone(int64_t zone, double minThermalOutput, double failSafePercent,
Bonnie Lo0e8fc392022-10-05 10:20:55 +080061 conf::CycleTime cycleTime, const SensorManager& mgr,
Delphine CC Chiu97889632023-11-06 11:32:46 +080062 sdbusplus::bus_t& bus, const char* objPath, bool defer,
63 bool accumulateSetPoint) :
Patrick Williamsd8c5a452022-04-07 16:08:56 -050064 ModeObject(bus, objPath,
65 defer ? ModeObject::action::defer_emit
66 : ModeObject::action::emit_object_added),
Ed Tanousd2768c52025-06-26 11:42:57 -070067 _zoneId(zone), _accumulateSetPoint(accumulateSetPoint),
James Feist3484bed2019-02-25 13:28:18 -080068 _minThermalOutputSetPt(minThermalOutput),
ykchiu9fe3a3c2023-05-11 13:43:54 +080069 _zoneFailSafePercent(failSafePercent), _cycleTime(cycleTime), _mgr(mgr)
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070070 {
Patrick Venturede79ee02019-05-08 14:50:00 -070071 if (loggingEnabled)
Patrick Venturec32e3fc2019-02-28 10:01:11 -080072 {
Patrick Venture89002db2019-05-08 15:02:55 -070073 _log.open(loggingPath + "/zone_" + std::to_string(zone) + ".log");
Patrick Venturec32e3fc2019-02-28 10:01:11 -080074 }
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070075 }
Patrick Ventured8012182018-03-08 08:21:38 -080076
Patrick Venture7a98c192020-08-12 08:35:16 -070077 bool getManualMode(void) const override;
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070078 /* Could put lock around this since it's accessed from two threads, but
79 * only one reader/one writer.
80 */
Josh Lehana4146eb2020-10-01 11:49:09 -070081
82 bool getRedundantWrite(void) const override;
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070083 void setManualMode(bool mode);
84 bool getFailSafeMode(void) const override;
Harvey Wua4270072024-05-29 16:11:13 +080085 void markSensorMissing(const std::string& name,
86 const std::string& failReason);
Delphine CC Chiu97889632023-11-06 11:32:46 +080087 bool getAccSetPoint(void) const override;
Patrick Venture7a98c192020-08-12 08:35:16 -070088
Bonnie Loc51ba912022-10-12 14:07:22 +080089 int64_t getZoneID(void) const override;
Nirav Shahccc8bb62022-02-17 21:06:51 -080090 void addSetPoint(double setPoint, const std::string& name) override;
Patrick Venture7a98c192020-08-12 08:35:16 -070091 double getMaxSetPointRequest(void) const override;
James Feist608304d2019-02-25 10:01:42 -080092 void addRPMCeiling(double ceiling) override;
Patrick Venture7a98c192020-08-12 08:35:16 -070093 void clearSetPoints(void) override;
94 void clearRPMCeilings(void) override;
Harvey Wu92f9f3c2023-11-07 09:23:35 +080095 double getFailSafePercent(void) override;
Harvey Wua4270072024-05-29 16:11:13 +080096 FailSafeSensorsMap getFailSafeSensors(void) const override;
Nirav Shahccc8bb62022-02-17 21:06:51 -080097 double getMinThermalSetPoint(void) const;
Bonnie Lo0e8fc392022-10-05 10:20:55 +080098 uint64_t getCycleIntervalTime(void) const override;
99 uint64_t getUpdateThermalsCycle(void) const override;
Patrick Ventured8012182018-03-08 08:21:38 -0800100
Patrick Venture2d8e7852018-10-30 19:14:07 -0700101 Sensor* getSensor(const std::string& name) override;
James Zheng6df8bb52024-11-27 23:38:47 +0000102 std::vector<std::string> getSensorNames(void) override;
Patrick Venture7a98c192020-08-12 08:35:16 -0700103 void determineMaxSetPointRequest(void) override;
104 void updateFanTelemetry(void) override;
105 void updateSensors(void) override;
106 void initializeCache(void) override;
Josh Lehanb3005752022-02-22 20:48:07 -0800107 void setOutputCache(std::string_view, const ValueCacheEntry&) override;
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700108 void dumpCache(void);
Josh Lehana4146eb2020-10-01 11:49:09 -0700109
Patrick Venture7a98c192020-08-12 08:35:16 -0700110 void processFans(void) override;
111 void processThermals(void) override;
Patrick Ventured8012182018-03-08 08:21:38 -0800112
James Feist22c257a2018-08-31 14:07:12 -0700113 void addFanPID(std::unique_ptr<Controller> pid);
114 void addThermalPID(std::unique_ptr<Controller> pid);
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700115 double getCachedValue(const std::string& name) override;
Josh Lehanb3005752022-02-22 20:48:07 -0800116 ValueCacheEntry getCachedValues(const std::string& name) override;
117
Josh Lehan3f0f7bc2023-02-13 01:45:29 -0800118 void addFanInput(const std::string& fan, bool missingAcceptable);
119 void addThermalInput(const std::string& therm, bool missingAcceptable);
Patrick Ventured8012182018-03-08 08:21:38 -0800120
Patrick Venture7a98c192020-08-12 08:35:16 -0700121 void initializeLog(void) override;
122 void writeLog(const std::string& value) override;
Patrick Ventured8012182018-03-08 08:21:38 -0800123
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700124 /* Method for setting the manual mode over dbus */
125 bool manual(bool value) override;
126 /* Method for reading whether in fail-safe mode over dbus */
127 bool failSafe() const override;
Harvey Wucc0232a2023-02-09 14:58:55 +0800128 /* Method for recording the maximum SetPoint PID config name */
129 std::string leader() const override;
ykchiu7c6d35d2023-05-10 17:01:46 +0800130 /* Method for control process for each loop at runtime */
Ed Tanousd2768c52025-06-26 11:42:57 -0700131 void addPidControlProcess(const std::string& name, const std::string& type,
Harvey Wu37180062023-10-02 09:42:50 +0800132 double setpoint, sdbusplus::bus_t& bus,
Ed Tanousd2768c52025-06-26 11:42:57 -0700133 const std::string& objPath, bool defer);
134 bool isPidProcessEnabled(const std::string& name);
Patrick Ventured8012182018-03-08 08:21:38 -0800135
Ed Tanousd2768c52025-06-26 11:42:57 -0700136 void addPidFailSafePercent(const std::vector<std::string>& inputs,
137 double percent);
ykchiu9fe3a3c2023-05-11 13:43:54 +0800138
Harvey Wu37180062023-10-02 09:42:50 +0800139 void updateThermalPowerDebugInterface(std::string pidName,
140 std::string leader, double input,
141 double output) override;
142
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700143 private:
Tom Tungdf1f1832022-11-14 19:26:52 +0800144 template <bool fanSensorLogging>
145 void processSensorInputs(const std::vector<std::string>& sensorInputs,
146 std::chrono::high_resolution_clock::time_point now)
147 {
148 for (const auto& sensorInput : sensorInputs)
149 {
150 auto sensor = _mgr.getSensor(sensorInput);
151 ReadReturn r = sensor->read();
152 _cachedValuesByName[sensorInput] = {r.value, r.unscaled};
153 int64_t timeout = sensor->getTimeout();
154 std::chrono::high_resolution_clock::time_point then = r.updated;
155
156 auto duration =
157 std::chrono::duration_cast<std::chrono::seconds>(now - then)
158 .count();
159 auto period = std::chrono::seconds(timeout).count();
160 /*
161 * TODO(venture): We should check when these were last read.
162 * However, these are the fans, so if I'm not getting updated values
163 * for them... what should I do?
164 */
165 if constexpr (fanSensorLogging)
166 {
167 if (loggingEnabled)
168 {
169 const auto& v = _cachedValuesByName[sensorInput];
170 _log << "," << v.scaled << "," << v.unscaled;
171 const auto& p = _cachedFanOutputs[sensorInput];
172 _log << "," << p.scaled << "," << p.unscaled;
173 }
174 }
175
176 if (debugEnabled)
177 {
178 std::cerr << sensorInput << " sensor reading: " << r.value
179 << "\n";
180 }
181
182 // check if fan fail.
183 if (sensor->getFailed())
184 {
Harvey Wua4270072024-05-29 16:11:13 +0800185 markSensorMissing(sensorInput, sensor->getFailReason());
Josh Lehan3f0f7bc2023-02-13 01:45:29 -0800186
Tom Tungdf1f1832022-11-14 19:26:52 +0800187 if (debugEnabled)
188 {
189 std::cerr << sensorInput << " sensor get failed\n";
190 }
191 }
192 else if (timeout != 0 && duration >= period)
193 {
Harvey Wua4270072024-05-29 16:11:13 +0800194 markSensorMissing(sensorInput, "Sensor timeout");
Josh Lehan3f0f7bc2023-02-13 01:45:29 -0800195
Tom Tungdf1f1832022-11-14 19:26:52 +0800196 if (debugEnabled)
197 {
198 std::cerr << sensorInput << " sensor timeout\n";
199 }
James Zheng6df8bb52024-11-27 23:38:47 +0000200 outputFailsafeLogWithZone(_zoneId, this->getFailSafeMode(),
201 sensorInput,
202 "The sensor has timed out.");
Tom Tungdf1f1832022-11-14 19:26:52 +0800203 }
204 else
205 {
206 // Check if it's in there: remove it.
207 auto kt = _failSafeSensors.find(sensorInput);
208 if (kt != _failSafeSensors.end())
209 {
210 if (debugEnabled)
211 {
212 std::cerr << sensorInput
213 << " is erased from failsafe sensor set\n";
214 }
Josh Lehan3f0f7bc2023-02-13 01:45:29 -0800215
Tom Tungdf1f1832022-11-14 19:26:52 +0800216 _failSafeSensors.erase(kt);
James Zheng6df8bb52024-11-27 23:38:47 +0000217 outputFailsafeLogWithZone(_zoneId, this->getFailSafeMode(),
218 sensorInput,
219 "The sensor has recovered.");
Tom Tungdf1f1832022-11-14 19:26:52 +0800220 }
221 }
222 }
223 }
224
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700225 std::ofstream _log;
Patrick Ventured8012182018-03-08 08:21:38 -0800226
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700227 const int64_t _zoneId;
Patrick Venturef7a2dd52019-07-16 14:31:13 -0700228 double _maximumSetPoint = 0;
Nirav Shahccc8bb62022-02-17 21:06:51 -0800229 std::string _maximumSetPointName;
230 std::string _maximumSetPointNamePrev;
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700231 bool _manualMode = false;
Josh Lehana4146eb2020-10-01 11:49:09 -0700232 bool _redundantWrite = false;
Delphine CC Chiu97889632023-11-06 11:32:46 +0800233 bool _accumulateSetPoint = false;
James Feist3484bed2019-02-25 13:28:18 -0800234 const double _minThermalOutputSetPt;
ykchiu9fe3a3c2023-05-11 13:43:54 +0800235 // Zone fail safe Percent setting by configuration.
236 const double _zoneFailSafePercent;
Bonnie Lo0e8fc392022-10-05 10:20:55 +0800237 const conf::CycleTime _cycleTime;
Patrick Ventured8012182018-03-08 08:21:38 -0800238
Harvey Wua4270072024-05-29 16:11:13 +0800239 /*
240 * <map key = sensor name, value = sensor fail reason and failsafe percent>
241 */
242 FailSafeSensorsMap _failSafeSensors;
Josh Lehan3f0f7bc2023-02-13 01:45:29 -0800243 std::set<std::string> _missingAcceptable;
Patrick Ventured8012182018-03-08 08:21:38 -0800244
Ed Tanousd2768c52025-06-26 11:42:57 -0700245 std::map<std::string, double> setPoints;
246 std::vector<double> rpmCeilings;
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700247 std::vector<std::string> _fanInputs;
248 std::vector<std::string> _thermalInputs;
Josh Lehanb3005752022-02-22 20:48:07 -0800249 std::map<std::string, ValueCacheEntry> _cachedValuesByName;
250 std::map<std::string, ValueCacheEntry> _cachedFanOutputs;
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700251 const SensorManager& _mgr;
Patrick Ventured8012182018-03-08 08:21:38 -0800252
James Feist22c257a2018-08-31 14:07:12 -0700253 std::vector<std::unique_ptr<Controller>> _fans;
254 std::vector<std::unique_ptr<Controller>> _thermals;
ykchiu7c6d35d2023-05-10 17:01:46 +0800255
256 std::map<std::string, std::unique_ptr<ProcessObject>> _pidsControlProcess;
ykchiu9fe3a3c2023-05-11 13:43:54 +0800257 /*
Harvey Wu92f9f3c2023-11-07 09:23:35 +0800258 * <key = sensor name, value = sensor failsafe percent>
259 * sensor fail safe Percent setting by each pid controller configuration.
ykchiu9fe3a3c2023-05-11 13:43:54 +0800260 */
Harvey Wu92f9f3c2023-11-07 09:23:35 +0800261 std::map<std::string, double> _sensorFailSafePercent;
Patrick Ventured8012182018-03-08 08:21:38 -0800262};
Patrick Venturea0764872020-08-08 07:48:43 -0700263
264} // namespace pid_control