Set failsafePwm by pid configuration
<motivation>
Current phosphor-pid-control service supports one zone with
one failsafepwm. However, for some platforms there are
different pluggable cards in a zone. Different combinations
may require different failsafe pwm settings. Why not just
use one zone failsafepwm for all the combinations? because if
we take power consumption or acoustic into consideration,
we will find that not all the cases need the same high
failsafepwm. Each case just need high enough failsafepwm
to cool down the system in that condition.
For example
case1: zone0 : gpuA card + motherboard in zone0
=>requires failsafepwm = 80
case2: zone1 : gpuB card + motherboard in zone0
=>requires failsafepwm = 60
In order to solve the problem described above , we propose
the design that. Each pidloop has its own failsafepwm.
The final failsafepwm will be calculated during building
zone process. The detailed design concept is described in
design concept section.
<design concept>
a zone has several pid loops, each one has its own pid
failsafe pwm defined in its configuration.
The calculation flow goes as below:
1.Take failsafepwm of the pidloops and the zone from the configuration
files, if any is missing , set it to zero.
2.Take max value of (zone failsafepwm and pid loops failsafepwm).
3.If the max value from 'step 2' is zero indicates none of failsafepwm
is configured, set it to default setting 100%.
<note>
1.this is intended for dbus configuration method, since one zone
may have different pidloops from different pluggable boards
entity json, but this design also works for static configuration
method, therefore, the zone with different boards will need
different failsafepwm.
2.keep it back compatible with original design , also take zone
failsafepwm into calculation.
Working example as below
Case1
Zone0:
zone0 pidloop failsafepwm = 60
gpuA pidloop failsafepwm = 70
Motherboard failsafepwm = 40
=>final failsafepwm = 70
Case2
Zone0:
zone0 pidloop failsafepwm = 60
gpuB pidloop failsafepwm = 80
Motherboard failsafepwm = 40
=>final failsafepwm = 80
Change-Id: I5aa1c6a7108f4520f41de5d8eba3075d021bbe79
Signed-off-by: ykchiu <Chiu.YK@inventec.com>
diff --git a/conf.hpp b/conf.hpp
index d7d34f5..f3811e4 100644
--- a/conf.hpp
+++ b/conf.hpp
@@ -40,6 +40,7 @@
double setpoint; // initial setpoint for thermal.
ec::pidinfo pidInfo; // pid details
ec::StepwiseInfo stepwiseInfo;
+ double failSafePercent;
};
struct CycleTime
diff --git a/dbus/dbusconfiguration.cpp b/dbus/dbusconfiguration.cpp
index 4f86ff6..d784b2c 100644
--- a/dbus/dbusconfiguration.cpp
+++ b/dbus/dbusconfiguration.cpp
@@ -317,6 +317,15 @@
getPIDAttribute(base, "SetPoint"));
}
+ int failsafepercent = 0;
+ auto findFailSafe = base.find("FailSafePercent");
+ if (findFailSafe != base.end())
+ {
+ failsafepercent = std::visit(VariantToDoubleVisitor(),
+ getPIDAttribute(base, "FailSafePercent"));
+ }
+ info.failSafePercent = failsafepercent;
+
if (thresholdProperty != nullptr)
{
std::string interface;
@@ -620,8 +629,15 @@
details.minThermalOutput = std::visit(VariantToDoubleVisitor(),
zone.at("MinThermalOutput"));
- details.failsafePercent = std::visit(VariantToDoubleVisitor(),
- zone.at("FailSafePercent"));
+
+ int failsafepercent = 0;
+ auto findFailSafe = zone.find("FailSafePercent");
+ if (findFailSafe != zone.end())
+ {
+ failsafepercent = std::visit(VariantToDoubleVisitor(),
+ zone.at("FailSafePercent"));
+ }
+ details.failsafePercent = failsafepercent;
getCycleTimeSetting(zone, index, "CycleIntervalTimeMS",
details.cycleTime.cycleIntervalTimeMS);
diff --git a/pid/builder.cpp b/pid/builder.cpp
index 08526fa..830c2fb 100644
--- a/pid/builder.cpp
+++ b/pid/builder.cpp
@@ -100,6 +100,7 @@
auto pid = FanController::createFanPid(zone.get(), name, inputs,
info.pidInfo);
zone->addFanPID(std::move(pid));
+ zone->addPidFailSafePercent(name, info.failSafePercent);
}
else if (isThermalType(info.type))
{
@@ -117,6 +118,7 @@
zone->addPidControlProcess(name, modeControlBus,
getPidControlPath(zoneId, name),
deferSignals);
+ zone->addPidFailSafePercent(name, info.failSafePercent);
}
else if (info.type == "stepwise")
{
@@ -131,6 +133,7 @@
zone->addPidControlProcess(name, modeControlBus,
getPidControlPath(zoneId, name),
deferSignals);
+ zone->addPidFailSafePercent(name, info.failSafePercent);
}
std::cerr << "inputs: ";
diff --git a/pid/buildjson.cpp b/pid/buildjson.cpp
index 1122f09..57ea943 100644
--- a/pid/buildjson.cpp
+++ b/pid/buildjson.cpp
@@ -62,6 +62,14 @@
derivativeCoeff->get_to(derivativeCoeffValue);
}
+ auto failSafePercent = j.find("FailSafePercent");
+ auto failSafePercentValue = 0;
+ if (failSafePercent != j.end())
+ {
+ failSafePercent->get_to(failSafePercentValue);
+ }
+ c.failSafePercent = failSafePercentValue;
+
if (c.type != "stepwise")
{
p.at("samplePeriod").get_to(c.pidInfo.ts);
diff --git a/pid/zone.cpp b/pid/zone.cpp
index b76fdec..a8c388a 100644
--- a/pid/zone.cpp
+++ b/pid/zone.cpp
@@ -405,6 +405,8 @@
// Start all sensors in fail-safe mode.
_failSafeSensors.insert(t);
}
+ // Initialize Pid FailSafePercent
+ initPidFailSafePercent();
}
void DbusPidZone::dumpCache(void)
@@ -484,4 +486,34 @@
return _pidsControlProcess[name]->enabled();
}
+void DbusPidZone::initPidFailSafePercent(void)
+{
+ // Currently, find the max failsafe percent pwm settings from zone and
+ // controller, and assign it to zone failsafe percent.
+
+ _failSafePercent = _zoneFailSafePercent;
+ std::cerr << "zone: Zone" << _zoneId
+ << " zoneFailSafePercent: " << _zoneFailSafePercent << "\n";
+
+ for (const auto& [name, value] : _pidsFailSafePercent)
+ {
+ _failSafePercent = std::max(_failSafePercent, value);
+ std::cerr << "pid: " << name << " failSafePercent: " << value << "\n";
+ }
+
+ // when the final failsafe percent is zero , it indicate no failsafe
+ // percent is configured , set it to 100% as the default setting.
+ if (_failSafePercent == 0)
+ {
+ _failSafePercent = 100;
+ }
+ std::cerr << "Final zone" << _zoneId
+ << " failSafePercent: " << _failSafePercent << "\n";
+}
+
+void DbusPidZone::addPidFailSafePercent(std::string name, double percent)
+{
+ _pidsFailSafePercent[name] = percent;
+}
+
} // namespace pid_control
diff --git a/pid/zone.hpp b/pid/zone.hpp
index 9604c73..53d90fd 100644
--- a/pid/zone.hpp
+++ b/pid/zone.hpp
@@ -48,7 +48,7 @@
: ModeObject::action::emit_object_added),
_zoneId(zone), _maximumSetPoint(),
_minThermalOutputSetPt(minThermalOutput),
- _failSafePercent(failSafePercent), _cycleTime(cycleTime), _mgr(mgr)
+ _zoneFailSafePercent(failSafePercent), _cycleTime(cycleTime), _mgr(mgr)
{
if (loggingEnabled)
{
@@ -107,6 +107,9 @@
std::string objPath, bool defer);
bool isPidProcessEnabled(std::string name);
+ void initPidFailSafePercent(void);
+ void addPidFailSafePercent(std::string name, double percent);
+
private:
template <bool fanSensorLogging>
void processSensorInputs(const std::vector<std::string>& sensorInputs,
@@ -189,7 +192,10 @@
bool _manualMode = false;
bool _redundantWrite = false;
const double _minThermalOutputSetPt;
- const double _failSafePercent;
+ // Current fail safe Percent.
+ double _failSafePercent;
+ // Zone fail safe Percent setting by configuration.
+ const double _zoneFailSafePercent;
const conf::CycleTime _cycleTime;
std::set<std::string> _failSafeSensors;
@@ -206,6 +212,11 @@
std::vector<std::unique_ptr<Controller>> _thermals;
std::map<std::string, std::unique_ptr<ProcessObject>> _pidsControlProcess;
+ /*
+ * <key = pidname, value = pid failsafe percent>
+ * Pid fail safe Percent setting by each pid controller configuration.
+ */
+ std::map<std::string, double> _pidsFailSafePercent;
};
} // namespace pid_control
diff --git a/test/pid_zone_unittest.cpp b/test/pid_zone_unittest.cpp
index 4eb3487..8c55a70 100644
--- a/test/pid_zone_unittest.cpp
+++ b/test/pid_zone_unittest.cpp
@@ -53,7 +53,7 @@
const char* objPath = "/path/";
int64_t zone = 1;
double minThermalOutput = 1000.0;
- double failSafePercent = 0.75;
+ double failSafePercent = 0;
conf::CycleTime cycleTime;
double d;
@@ -122,7 +122,7 @@
sdbusplus::SdBusMock sdbus_mock_enable;
int64_t zoneId = 1;
double minThermalOutput = 1000.0;
- double failSafePercent = 0.75;
+ double failSafePercent = 0;
bool defer = true;
const char* objPath = "/path/";
SensorManager mgr;
@@ -291,7 +291,42 @@
TEST_F(PidZoneTest, GetFailSafePercent_ReturnsExpected)
{
// Verify the value used to create the object is stored.
- EXPECT_EQ(failSafePercent, zone->getFailSafePercent());
+ // when the final failsafe percent is zero , it indicate
+ // no failsafe percent is configured , set it to 100% as
+ // the default setting.
+
+ std::vector<double> values = {0, 0, 0};
+ int64_t defaultPercent = 100;
+
+ zone->addPidFailSafePercent("temp1", values[0]);
+ zone->addPidFailSafePercent("temp2", values[1]);
+ zone->addPidFailSafePercent("temp3", values[2]);
+
+ zone->initPidFailSafePercent();
+
+ EXPECT_EQ(defaultPercent, zone->getFailSafePercent());
+}
+
+TEST_F(PidZoneTest, GetFailSafePercent_VerifyReturnsExpected)
+{
+ // Tests adding PID controller with FailSafePercent to the zone,
+ // and verifies it's returned as expected.
+
+ std::vector<double> values = {60, 80, 70};
+ double max_value = 0;
+
+ for (const auto& value : values)
+ {
+ max_value = std::max(max_value, value);
+ }
+
+ zone->addPidFailSafePercent("temp1", values[0]);
+ zone->addPidFailSafePercent("temp2", values[1]);
+ zone->addPidFailSafePercent("temp3", values[2]);
+
+ zone->initPidFailSafePercent();
+
+ EXPECT_EQ(max_value, zone->getFailSafePercent());
}
TEST_F(PidZoneTest, ThermalInputs_FailsafeToValid_ReadsSensors)