blob: 85a90648e45145b4437f73b18ec1b5bda7c12c3d [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 Feist22c257a2018-08-31 14:07:12 -07005#include "pidcontroller.hpp"
Patrick Ventureda4a5dd2018-08-31 09:42:48 -07006#include "sensors/manager.hpp"
7#include "sensors/sensor.hpp"
Patrick Venturec32e3fc2019-02-28 10:01:11 -08008#include "tuning.hpp"
Patrick Venture1a153792020-08-11 08:41:47 -07009#include "zone_interface.hpp"
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070010
Patrick Venturea83a3ec2020-08-04 09:52:05 -070011#include <sdbusplus/bus.hpp>
12#include <sdbusplus/server.hpp>
13#include <xyz/openbmc_project/Control/Mode/server.hpp>
Harvey Wucc0232a2023-02-09 14:58:55 +080014#include <xyz/openbmc_project/Debug/Pid/Zone/server.hpp>
ykchiu7c6d35d2023-05-10 17:01:46 +080015#include <xyz/openbmc_project/Object/Enable/server.hpp>
Patrick Venturea83a3ec2020-08-04 09:52:05 -070016
Patrick Ventured8012182018-03-08 08:21:38 -080017#include <fstream>
Tom Tungdf1f1832022-11-14 19:26:52 +080018#include <iostream>
Patrick Ventured8012182018-03-08 08:21:38 -080019#include <map>
20#include <memory>
21#include <set>
22#include <string>
23#include <vector>
24
Patrick Ventured8012182018-03-08 08:21:38 -080025template <typename... T>
Patrick Williamsb228bc32022-07-22 19:26:56 -050026using ServerObject = typename sdbusplus::server::object_t<T...>;
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070027using ModeInterface = sdbusplus::xyz::openbmc_project::Control::server::Mode;
Harvey Wucc0232a2023-02-09 14:58:55 +080028using DebugZoneInterface =
29 sdbusplus::xyz::openbmc_project::Debug::Pid::server::Zone;
30using ModeObject = ServerObject<ModeInterface, DebugZoneInterface>;
ykchiu7c6d35d2023-05-10 17:01:46 +080031using ProcessInterface =
32 sdbusplus::xyz::openbmc_project::Object::server::Enable;
33using ProcessObject = ServerObject<ProcessInterface>;
Patrick Ventured8012182018-03-08 08:21:38 -080034
Patrick Venturea0764872020-08-08 07:48:43 -070035namespace pid_control
36{
37
Patrick Ventured8012182018-03-08 08:21:38 -080038/*
Patrick Venture597ebd62020-08-11 08:48:19 -070039 * The DbusPidZone inherits from the Mode object so that it can listen for
40 * control mode changes. It primarily holds all PID loops and holds the sensor
41 * value cache that's used per iteration of the PID loops.
Patrick Ventured8012182018-03-08 08:21:38 -080042 */
Patrick Venture597ebd62020-08-11 08:48:19 -070043class DbusPidZone : public ZoneInterface, public ModeObject
Patrick Ventured8012182018-03-08 08:21:38 -080044{
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070045 public:
Patrick Venture597ebd62020-08-11 08:48:19 -070046 DbusPidZone(int64_t zone, double minThermalOutput, double failSafePercent,
Bonnie Lo0e8fc392022-10-05 10:20:55 +080047 conf::CycleTime cycleTime, const SensorManager& mgr,
48 sdbusplus::bus_t& bus, const char* objPath, bool defer) :
Patrick Williamsd8c5a452022-04-07 16:08:56 -050049 ModeObject(bus, objPath,
50 defer ? ModeObject::action::defer_emit
51 : ModeObject::action::emit_object_added),
Patrick Venturef7a2dd52019-07-16 14:31:13 -070052 _zoneId(zone), _maximumSetPoint(),
James Feist3484bed2019-02-25 13:28:18 -080053 _minThermalOutputSetPt(minThermalOutput),
ykchiu9fe3a3c2023-05-11 13:43:54 +080054 _zoneFailSafePercent(failSafePercent), _cycleTime(cycleTime), _mgr(mgr)
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070055 {
Patrick Venturede79ee02019-05-08 14:50:00 -070056 if (loggingEnabled)
Patrick Venturec32e3fc2019-02-28 10:01:11 -080057 {
Patrick Venture89002db2019-05-08 15:02:55 -070058 _log.open(loggingPath + "/zone_" + std::to_string(zone) + ".log");
Patrick Venturec32e3fc2019-02-28 10:01:11 -080059 }
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070060 }
Patrick Ventured8012182018-03-08 08:21:38 -080061
Patrick Venture7a98c192020-08-12 08:35:16 -070062 bool getManualMode(void) const override;
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070063 /* Could put lock around this since it's accessed from two threads, but
64 * only one reader/one writer.
65 */
Josh Lehana4146eb2020-10-01 11:49:09 -070066
67 bool getRedundantWrite(void) const override;
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070068 void setManualMode(bool mode);
69 bool getFailSafeMode(void) const override;
Patrick Venture7a98c192020-08-12 08:35:16 -070070
Bonnie Loc51ba912022-10-12 14:07:22 +080071 int64_t getZoneID(void) const override;
Nirav Shahccc8bb62022-02-17 21:06:51 -080072 void addSetPoint(double setPoint, const std::string& name) override;
Patrick Venture7a98c192020-08-12 08:35:16 -070073 double getMaxSetPointRequest(void) const override;
James Feist608304d2019-02-25 10:01:42 -080074 void addRPMCeiling(double ceiling) override;
Patrick Venture7a98c192020-08-12 08:35:16 -070075 void clearSetPoints(void) override;
76 void clearRPMCeilings(void) override;
Patrick Venture5f59c0f2018-11-11 12:55:14 -080077 double getFailSafePercent(void) const override;
Nirav Shahccc8bb62022-02-17 21:06:51 -080078 double getMinThermalSetPoint(void) const;
Bonnie Lo0e8fc392022-10-05 10:20:55 +080079 uint64_t getCycleIntervalTime(void) const override;
80 uint64_t getUpdateThermalsCycle(void) const override;
Patrick Ventured8012182018-03-08 08:21:38 -080081
Patrick Venture2d8e7852018-10-30 19:14:07 -070082 Sensor* getSensor(const std::string& name) override;
Patrick Venture7a98c192020-08-12 08:35:16 -070083 void determineMaxSetPointRequest(void) override;
84 void updateFanTelemetry(void) override;
85 void updateSensors(void) override;
86 void initializeCache(void) override;
Josh Lehanb3005752022-02-22 20:48:07 -080087 void setOutputCache(std::string_view, const ValueCacheEntry&) override;
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070088 void dumpCache(void);
Josh Lehana4146eb2020-10-01 11:49:09 -070089
Patrick Venture7a98c192020-08-12 08:35:16 -070090 void processFans(void) override;
91 void processThermals(void) override;
Patrick Ventured8012182018-03-08 08:21:38 -080092
James Feist22c257a2018-08-31 14:07:12 -070093 void addFanPID(std::unique_ptr<Controller> pid);
94 void addThermalPID(std::unique_ptr<Controller> pid);
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070095 double getCachedValue(const std::string& name) override;
Josh Lehanb3005752022-02-22 20:48:07 -080096 ValueCacheEntry getCachedValues(const std::string& name) override;
97
Patrick Venturec399f6f2018-10-30 19:24:47 -070098 void addFanInput(const std::string& fan);
99 void addThermalInput(const std::string& therm);
Patrick Ventured8012182018-03-08 08:21:38 -0800100
Patrick Venture7a98c192020-08-12 08:35:16 -0700101 void initializeLog(void) override;
102 void writeLog(const std::string& value) override;
Patrick Ventured8012182018-03-08 08:21:38 -0800103
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700104 /* Method for setting the manual mode over dbus */
105 bool manual(bool value) override;
106 /* Method for reading whether in fail-safe mode over dbus */
107 bool failSafe() const override;
Harvey Wucc0232a2023-02-09 14:58:55 +0800108 /* Method for recording the maximum SetPoint PID config name */
109 std::string leader() const override;
ykchiu7c6d35d2023-05-10 17:01:46 +0800110 /* Method for control process for each loop at runtime */
111 void addPidControlProcess(std::string name, sdbusplus::bus_t& bus,
112 std::string objPath, bool defer);
113 bool isPidProcessEnabled(std::string name);
Patrick Ventured8012182018-03-08 08:21:38 -0800114
ykchiu9fe3a3c2023-05-11 13:43:54 +0800115 void initPidFailSafePercent(void);
116 void addPidFailSafePercent(std::string name, double percent);
117
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700118 private:
Tom Tungdf1f1832022-11-14 19:26:52 +0800119 template <bool fanSensorLogging>
120 void processSensorInputs(const std::vector<std::string>& sensorInputs,
121 std::chrono::high_resolution_clock::time_point now)
122 {
123 for (const auto& sensorInput : sensorInputs)
124 {
125 auto sensor = _mgr.getSensor(sensorInput);
126 ReadReturn r = sensor->read();
127 _cachedValuesByName[sensorInput] = {r.value, r.unscaled};
128 int64_t timeout = sensor->getTimeout();
129 std::chrono::high_resolution_clock::time_point then = r.updated;
130
131 auto duration =
132 std::chrono::duration_cast<std::chrono::seconds>(now - then)
133 .count();
134 auto period = std::chrono::seconds(timeout).count();
135 /*
136 * TODO(venture): We should check when these were last read.
137 * However, these are the fans, so if I'm not getting updated values
138 * for them... what should I do?
139 */
140 if constexpr (fanSensorLogging)
141 {
142 if (loggingEnabled)
143 {
144 const auto& v = _cachedValuesByName[sensorInput];
145 _log << "," << v.scaled << "," << v.unscaled;
146 const auto& p = _cachedFanOutputs[sensorInput];
147 _log << "," << p.scaled << "," << p.unscaled;
148 }
149 }
150
151 if (debugEnabled)
152 {
153 std::cerr << sensorInput << " sensor reading: " << r.value
154 << "\n";
155 }
156
157 // check if fan fail.
158 if (sensor->getFailed())
159 {
160 _failSafeSensors.insert(sensorInput);
161 if (debugEnabled)
162 {
163 std::cerr << sensorInput << " sensor get failed\n";
164 }
165 }
166 else if (timeout != 0 && duration >= period)
167 {
168 _failSafeSensors.insert(sensorInput);
169 if (debugEnabled)
170 {
171 std::cerr << sensorInput << " sensor timeout\n";
172 }
173 }
174 else
175 {
176 // Check if it's in there: remove it.
177 auto kt = _failSafeSensors.find(sensorInput);
178 if (kt != _failSafeSensors.end())
179 {
180 if (debugEnabled)
181 {
182 std::cerr << sensorInput
183 << " is erased from failsafe sensor set\n";
184 }
185 _failSafeSensors.erase(kt);
186 }
187 }
188 }
189 }
190
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700191 std::ofstream _log;
Patrick Ventured8012182018-03-08 08:21:38 -0800192
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700193 const int64_t _zoneId;
Patrick Venturef7a2dd52019-07-16 14:31:13 -0700194 double _maximumSetPoint = 0;
Nirav Shahccc8bb62022-02-17 21:06:51 -0800195 std::string _maximumSetPointName;
196 std::string _maximumSetPointNamePrev;
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700197 bool _manualMode = false;
Josh Lehana4146eb2020-10-01 11:49:09 -0700198 bool _redundantWrite = false;
James Feist3484bed2019-02-25 13:28:18 -0800199 const double _minThermalOutputSetPt;
ykchiu9fe3a3c2023-05-11 13:43:54 +0800200 // Current fail safe Percent.
201 double _failSafePercent;
202 // Zone fail safe Percent setting by configuration.
203 const double _zoneFailSafePercent;
Bonnie Lo0e8fc392022-10-05 10:20:55 +0800204 const conf::CycleTime _cycleTime;
Patrick Ventured8012182018-03-08 08:21:38 -0800205
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700206 std::set<std::string> _failSafeSensors;
Patrick Ventured8012182018-03-08 08:21:38 -0800207
Patrick Venture9bbf3332019-07-16 10:50:37 -0700208 std::vector<double> _SetPoints;
James Feist608304d2019-02-25 10:01:42 -0800209 std::vector<double> _RPMCeilings;
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700210 std::vector<std::string> _fanInputs;
211 std::vector<std::string> _thermalInputs;
Josh Lehanb3005752022-02-22 20:48:07 -0800212 std::map<std::string, ValueCacheEntry> _cachedValuesByName;
213 std::map<std::string, ValueCacheEntry> _cachedFanOutputs;
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700214 const SensorManager& _mgr;
Patrick Ventured8012182018-03-08 08:21:38 -0800215
James Feist22c257a2018-08-31 14:07:12 -0700216 std::vector<std::unique_ptr<Controller>> _fans;
217 std::vector<std::unique_ptr<Controller>> _thermals;
ykchiu7c6d35d2023-05-10 17:01:46 +0800218
219 std::map<std::string, std::unique_ptr<ProcessObject>> _pidsControlProcess;
ykchiu9fe3a3c2023-05-11 13:43:54 +0800220 /*
221 * <key = pidname, value = pid failsafe percent>
222 * Pid fail safe Percent setting by each pid controller configuration.
223 */
224 std::map<std::string, double> _pidsFailSafePercent;
Patrick Ventured8012182018-03-08 08:21:38 -0800225};
Patrick Venturea0764872020-08-08 07:48:43 -0700226
227} // namespace pid_control