1d8012181SPatrick Venture #pragma once 2d8012181SPatrick Venture 3da4a5dd1SPatrick Venture #include "conf.hpp" 4da4a5dd1SPatrick Venture #include "controller.hpp" 5*6df8bb50SJames Zheng #include "failsafeloggers/failsafe_logger_utility.hpp" 622c257abSJames Feist #include "pidcontroller.hpp" 7da4a5dd1SPatrick Venture #include "sensors/manager.hpp" 8da4a5dd1SPatrick Venture #include "sensors/sensor.hpp" 9c32e3fc5SPatrick Venture #include "tuning.hpp" 101a153794SPatrick Venture #include "zone_interface.hpp" 11da4a5dd1SPatrick Venture 12a83a3eccSPatrick Venture #include <sdbusplus/bus.hpp> 13a83a3eccSPatrick Venture #include <sdbusplus/server.hpp> 14a83a3eccSPatrick Venture #include <xyz/openbmc_project/Control/Mode/server.hpp> 1537180062SHarvey Wu #include <xyz/openbmc_project/Debug/Pid/ThermalPower/server.hpp> 16cc0232afSHarvey Wu #include <xyz/openbmc_project/Debug/Pid/Zone/server.hpp> 177c6d35d5Sykchiu #include <xyz/openbmc_project/Object/Enable/server.hpp> 18a83a3eccSPatrick Venture 19d8012181SPatrick Venture #include <fstream> 20df1f183fSTom Tung #include <iostream> 21d8012181SPatrick Venture #include <map> 22d8012181SPatrick Venture #include <memory> 23d8012181SPatrick Venture #include <set> 24d8012181SPatrick Venture #include <string> 25d8012181SPatrick Venture #include <vector> 26d8012181SPatrick Venture 27d8012181SPatrick Venture template <typename... T> 28b228bc30SPatrick Williams using ServerObject = typename sdbusplus::server::object_t<T...>; 29da4a5dd1SPatrick Venture using ModeInterface = sdbusplus::xyz::openbmc_project::Control::server::Mode; 30cc0232afSHarvey Wu using DebugZoneInterface = 31cc0232afSHarvey Wu sdbusplus::xyz::openbmc_project::Debug::Pid::server::Zone; 32cc0232afSHarvey Wu using ModeObject = ServerObject<ModeInterface, DebugZoneInterface>; 337c6d35d5Sykchiu using ProcessInterface = 347c6d35d5Sykchiu sdbusplus::xyz::openbmc_project::Object::server::Enable; 3537180062SHarvey Wu using DebugThermalPowerInterface = 3637180062SHarvey Wu sdbusplus::xyz::openbmc_project::Debug::Pid::server::ThermalPower; 3737180062SHarvey Wu using ProcessObject = 3837180062SHarvey Wu ServerObject<ProcessInterface, DebugThermalPowerInterface>; 39d8012181SPatrick Venture 40a076487aSPatrick Venture namespace pid_control 41a076487aSPatrick Venture { 42a076487aSPatrick Venture 43d8012181SPatrick Venture /* 44597ebd67SPatrick Venture * The DbusPidZone inherits from the Mode object so that it can listen for 45597ebd67SPatrick Venture * control mode changes. It primarily holds all PID loops and holds the sensor 46597ebd67SPatrick Venture * value cache that's used per iteration of the PID loops. 47d8012181SPatrick Venture */ 48597ebd67SPatrick Venture class DbusPidZone : public ZoneInterface, public ModeObject 49d8012181SPatrick Venture { 50d8012181SPatrick Venture public: DbusPidZone(int64_t zone,double minThermalOutput,double failSafePercent,conf::CycleTime cycleTime,const SensorManager & mgr,sdbusplus::bus_t & bus,const char * objPath,bool defer,bool accumulateSetPoint)51597ebd67SPatrick Venture DbusPidZone(int64_t zone, double minThermalOutput, double failSafePercent, 520e8fc398SBonnie Lo conf::CycleTime cycleTime, const SensorManager& mgr, 539788963cSDelphine CC Chiu sdbusplus::bus_t& bus, const char* objPath, bool defer, 549788963cSDelphine CC Chiu bool accumulateSetPoint) : 55d8c5a45cSPatrick Williams ModeObject(bus, objPath, 56d8c5a45cSPatrick Williams defer ? ModeObject::action::defer_emit 57d8c5a45cSPatrick Williams : ModeObject::action::emit_object_added), 58f7a2dd5cSPatrick Venture _zoneId(zone), _maximumSetPoint(), 599788963cSDelphine CC Chiu _accumulateSetPoint(accumulateSetPoint), 603484bedaSJames Feist _minThermalOutputSetPt(minThermalOutput), 619fe3a3c7Sykchiu _zoneFailSafePercent(failSafePercent), _cycleTime(cycleTime), _mgr(mgr) 62d8012181SPatrick Venture { 63de79ee05SPatrick Venture if (loggingEnabled) 64c32e3fc5SPatrick Venture { 6589002dbdSPatrick Venture _log.open(loggingPath + "/zone_" + std::to_string(zone) + ".log"); 66c32e3fc5SPatrick Venture } 67d8012181SPatrick Venture } 68d8012181SPatrick Venture 697a98c19aSPatrick Venture bool getManualMode(void) const override; 70d8012181SPatrick Venture /* Could put lock around this since it's accessed from two threads, but 71d8012181SPatrick Venture * only one reader/one writer. 72d8012181SPatrick Venture */ 73a4146eb1SJosh Lehan 74a4146eb1SJosh Lehan bool getRedundantWrite(void) const override; 75d8012181SPatrick Venture void setManualMode(bool mode); 76a58197cfSPatrick Venture bool getFailSafeMode(void) const override; 773f0f7bc3SJosh Lehan void markSensorMissing(const std::string& name); 789788963cSDelphine CC Chiu bool getAccSetPoint(void) const override; 797a98c19aSPatrick Venture 80c51ba919SBonnie Lo int64_t getZoneID(void) const override; 81ccc8bb62SNirav Shah void addSetPoint(double setPoint, const std::string& name) override; 827a98c19aSPatrick Venture double getMaxSetPointRequest(void) const override; 83608304daSJames Feist void addRPMCeiling(double ceiling) override; 847a98c19aSPatrick Venture void clearSetPoints(void) override; 857a98c19aSPatrick Venture void clearRPMCeilings(void) override; 8692f9f3c8SHarvey Wu double getFailSafePercent(void) override; 87ccc8bb62SNirav Shah double getMinThermalSetPoint(void) const; 880e8fc398SBonnie Lo uint64_t getCycleIntervalTime(void) const override; 890e8fc398SBonnie Lo uint64_t getUpdateThermalsCycle(void) const override; 90d8012181SPatrick Venture 912d8e7851SPatrick Venture Sensor* getSensor(const std::string& name) override; 92*6df8bb50SJames Zheng std::vector<std::string> getSensorNames(void) override; 937a98c19aSPatrick Venture void determineMaxSetPointRequest(void) override; 947a98c19aSPatrick Venture void updateFanTelemetry(void) override; 957a98c19aSPatrick Venture void updateSensors(void) override; 967a98c19aSPatrick Venture void initializeCache(void) override; 97b300575eSJosh Lehan void setOutputCache(std::string_view, const ValueCacheEntry&) override; 98d8012181SPatrick Venture void dumpCache(void); 99a4146eb1SJosh Lehan 1007a98c19aSPatrick Venture void processFans(void) override; 1017a98c19aSPatrick Venture void processThermals(void) override; 102d8012181SPatrick Venture 10322c257abSJames Feist void addFanPID(std::unique_ptr<Controller> pid); 10422c257abSJames Feist void addThermalPID(std::unique_ptr<Controller> pid); 105a58197cfSPatrick Venture double getCachedValue(const std::string& name) override; 106b300575eSJosh Lehan ValueCacheEntry getCachedValues(const std::string& name) override; 107b300575eSJosh Lehan 1083f0f7bc3SJosh Lehan void addFanInput(const std::string& fan, bool missingAcceptable); 1093f0f7bc3SJosh Lehan void addThermalInput(const std::string& therm, bool missingAcceptable); 110d8012181SPatrick Venture 1117a98c19aSPatrick Venture void initializeLog(void) override; 1127a98c19aSPatrick Venture void writeLog(const std::string& value) override; 113d8012181SPatrick Venture 114d8012181SPatrick Venture /* Method for setting the manual mode over dbus */ 115d8012181SPatrick Venture bool manual(bool value) override; 116d8012181SPatrick Venture /* Method for reading whether in fail-safe mode over dbus */ 117d8012181SPatrick Venture bool failSafe() const override; 118cc0232afSHarvey Wu /* Method for recording the maximum SetPoint PID config name */ 119cc0232afSHarvey Wu std::string leader() const override; 1207c6d35d5Sykchiu /* Method for control process for each loop at runtime */ 12137180062SHarvey Wu void addPidControlProcess(std::string name, std::string type, 12237180062SHarvey Wu double setpoint, sdbusplus::bus_t& bus, 1237c6d35d5Sykchiu std::string objPath, bool defer); 1247c6d35d5Sykchiu bool isPidProcessEnabled(std::string name); 125d8012181SPatrick Venture 12692f9f3c8SHarvey Wu void addPidFailSafePercent(std::vector<std::string> inputs, double percent); 1279fe3a3c7Sykchiu 12837180062SHarvey Wu void updateThermalPowerDebugInterface(std::string pidName, 12937180062SHarvey Wu std::string leader, double input, 13037180062SHarvey Wu double output) override; 13137180062SHarvey Wu 132d8012181SPatrick Venture private: 133df1f183fSTom Tung template <bool fanSensorLogging> processSensorInputs(const std::vector<std::string> & sensorInputs,std::chrono::high_resolution_clock::time_point now)134df1f183fSTom Tung void processSensorInputs(const std::vector<std::string>& sensorInputs, 135df1f183fSTom Tung std::chrono::high_resolution_clock::time_point now) 136df1f183fSTom Tung { 137df1f183fSTom Tung for (const auto& sensorInput : sensorInputs) 138df1f183fSTom Tung { 139df1f183fSTom Tung auto sensor = _mgr.getSensor(sensorInput); 140df1f183fSTom Tung ReadReturn r = sensor->read(); 141df1f183fSTom Tung _cachedValuesByName[sensorInput] = {r.value, r.unscaled}; 142df1f183fSTom Tung int64_t timeout = sensor->getTimeout(); 143df1f183fSTom Tung std::chrono::high_resolution_clock::time_point then = r.updated; 144df1f183fSTom Tung 145df1f183fSTom Tung auto duration = 146df1f183fSTom Tung std::chrono::duration_cast<std::chrono::seconds>(now - then) 147df1f183fSTom Tung .count(); 148df1f183fSTom Tung auto period = std::chrono::seconds(timeout).count(); 149df1f183fSTom Tung /* 150df1f183fSTom Tung * TODO(venture): We should check when these were last read. 151df1f183fSTom Tung * However, these are the fans, so if I'm not getting updated values 152df1f183fSTom Tung * for them... what should I do? 153df1f183fSTom Tung */ 154df1f183fSTom Tung if constexpr (fanSensorLogging) 155df1f183fSTom Tung { 156df1f183fSTom Tung if (loggingEnabled) 157df1f183fSTom Tung { 158df1f183fSTom Tung const auto& v = _cachedValuesByName[sensorInput]; 159df1f183fSTom Tung _log << "," << v.scaled << "," << v.unscaled; 160df1f183fSTom Tung const auto& p = _cachedFanOutputs[sensorInput]; 161df1f183fSTom Tung _log << "," << p.scaled << "," << p.unscaled; 162df1f183fSTom Tung } 163df1f183fSTom Tung } 164df1f183fSTom Tung 165df1f183fSTom Tung if (debugEnabled) 166df1f183fSTom Tung { 167df1f183fSTom Tung std::cerr << sensorInput << " sensor reading: " << r.value 168df1f183fSTom Tung << "\n"; 169df1f183fSTom Tung } 170df1f183fSTom Tung 171df1f183fSTom Tung // check if fan fail. 172df1f183fSTom Tung if (sensor->getFailed()) 173df1f183fSTom Tung { 1743f0f7bc3SJosh Lehan markSensorMissing(sensorInput); 1753f0f7bc3SJosh Lehan 176df1f183fSTom Tung if (debugEnabled) 177df1f183fSTom Tung { 178df1f183fSTom Tung std::cerr << sensorInput << " sensor get failed\n"; 179df1f183fSTom Tung } 180df1f183fSTom Tung } 181df1f183fSTom Tung else if (timeout != 0 && duration >= period) 182df1f183fSTom Tung { 1833f0f7bc3SJosh Lehan markSensorMissing(sensorInput); 1843f0f7bc3SJosh Lehan 185df1f183fSTom Tung if (debugEnabled) 186df1f183fSTom Tung { 187df1f183fSTom Tung std::cerr << sensorInput << " sensor timeout\n"; 188df1f183fSTom Tung } 189*6df8bb50SJames Zheng outputFailsafeLogWithZone(_zoneId, this->getFailSafeMode(), 190*6df8bb50SJames Zheng sensorInput, 191*6df8bb50SJames Zheng "The sensor has timed out."); 192df1f183fSTom Tung } 193df1f183fSTom Tung else 194df1f183fSTom Tung { 195df1f183fSTom Tung // Check if it's in there: remove it. 196df1f183fSTom Tung auto kt = _failSafeSensors.find(sensorInput); 197df1f183fSTom Tung if (kt != _failSafeSensors.end()) 198df1f183fSTom Tung { 199df1f183fSTom Tung if (debugEnabled) 200df1f183fSTom Tung { 201df1f183fSTom Tung std::cerr << sensorInput 202df1f183fSTom Tung << " is erased from failsafe sensor set\n"; 203df1f183fSTom Tung } 2043f0f7bc3SJosh Lehan 205df1f183fSTom Tung _failSafeSensors.erase(kt); 206*6df8bb50SJames Zheng outputFailsafeLogWithZone(_zoneId, this->getFailSafeMode(), 207*6df8bb50SJames Zheng sensorInput, 208*6df8bb50SJames Zheng "The sensor has recovered."); 209df1f183fSTom Tung } 210df1f183fSTom Tung } 211df1f183fSTom Tung } 212df1f183fSTom Tung } 213df1f183fSTom Tung 214d8012181SPatrick Venture std::ofstream _log; 215d8012181SPatrick Venture 216d8012181SPatrick Venture const int64_t _zoneId; 217f7a2dd5cSPatrick Venture double _maximumSetPoint = 0; 218ccc8bb62SNirav Shah std::string _maximumSetPointName; 219ccc8bb62SNirav Shah std::string _maximumSetPointNamePrev; 220d8012181SPatrick Venture bool _manualMode = false; 221a4146eb1SJosh Lehan bool _redundantWrite = false; 2229788963cSDelphine CC Chiu bool _accumulateSetPoint = false; 2233484bedaSJames Feist const double _minThermalOutputSetPt; 2249fe3a3c7Sykchiu // Zone fail safe Percent setting by configuration. 2259fe3a3c7Sykchiu const double _zoneFailSafePercent; 2260e8fc398SBonnie Lo const conf::CycleTime _cycleTime; 227d8012181SPatrick Venture 22892f9f3c8SHarvey Wu std::map<std::string, double> _failSafeSensors; 2293f0f7bc3SJosh Lehan std::set<std::string> _missingAcceptable; 230d8012181SPatrick Venture 2319788963cSDelphine CC Chiu std::map<std::string, double> _SetPoints; 232608304daSJames Feist std::vector<double> _RPMCeilings; 233d8012181SPatrick Venture std::vector<std::string> _fanInputs; 234d8012181SPatrick Venture std::vector<std::string> _thermalInputs; 235b300575eSJosh Lehan std::map<std::string, ValueCacheEntry> _cachedValuesByName; 236b300575eSJosh Lehan std::map<std::string, ValueCacheEntry> _cachedFanOutputs; 237fe75b193SPatrick Venture const SensorManager& _mgr; 238d8012181SPatrick Venture 23922c257abSJames Feist std::vector<std::unique_ptr<Controller>> _fans; 24022c257abSJames Feist std::vector<std::unique_ptr<Controller>> _thermals; 2417c6d35d5Sykchiu 2427c6d35d5Sykchiu std::map<std::string, std::unique_ptr<ProcessObject>> _pidsControlProcess; 2439fe3a3c7Sykchiu /* 24492f9f3c8SHarvey Wu * <key = sensor name, value = sensor failsafe percent> 24592f9f3c8SHarvey Wu * sensor fail safe Percent setting by each pid controller configuration. 2469fe3a3c7Sykchiu */ 24792f9f3c8SHarvey Wu std::map<std::string, double> _sensorFailSafePercent; 248d8012181SPatrick Venture }; 249a076487aSPatrick Venture 250a076487aSPatrick Venture } // namespace pid_control 251