Support multiple sensors of same fru_type/label
There are some DDR5 DIMMs that have multiple DRAM temperature sensors,
of which we only care about the hotter one.
As the OCC reports these with the same fru_type and label values, the
code will need to read them both, and then just put the maximum value on
D-Bus.
Support this generically by first looping through all of the sysfs files
and saving the temperature values along with the calculated D-Bus object
path, handling the multiple sensor case by only storing the maximum
value, and then looping through the saved values and putting them on
D-Bus.
Tested:
Found sensors 33 and 34 are the same fru type and label:
temp33_fru_type:2
temp33_label:3489726464
temp33_input:38000
temp34_fru_type:2
temp34_label:3489726464
temp34_input:39000
Before change, the cooler one was on D-Bus:
```
d 38
```
After change, the hotter one was:
```
temp33_input:39000
temp34_input:41000
d 41
```
Change-Id: Ida632b9784209079d9d1bfc6c21918cd65be6a1f
Signed-off-by: Matt Spinler <spinler@us.ibm.com>
diff --git a/occ_manager.cpp b/occ_manager.cpp
index 69d3bc9..700b7af 100644
--- a/occ_manager.cpp
+++ b/occ_manager.cpp
@@ -762,6 +762,12 @@
#ifdef READ_OCC_SENSORS
void Manager::readTempSensors(const fs::path& path, uint32_t id)
{
+ // There may be more than one sensor with the same FRU type
+ // and label so make two passes: the first to read the temps
+ // from sysfs, and the second to put them on D-Bus after
+ // resolving any conflicts.
+ std::map<std::string, double> sensorData;
+
std::regex expr{"temp\\d+_label$"}; // Example: temp5_label
for (auto& file : fs::directory_iterator(path))
{
@@ -911,12 +917,13 @@
// NOTE: if OCC sends back 0xFF kernal sets this fault value to 1.
if (faultValue != 0)
{
- dbus::OccDBusSensors::getOccDBus().setValue(
- sensorPath, std::numeric_limits<double>::quiet_NaN());
-
- dbus::OccDBusSensors::getOccDBus().setOperationalStatus(sensorPath,
- false);
-
+ // For cases when there are multiple readings per fru type/label,
+ // don't overwrite a good value with an NaN.
+ if (!sensorData.contains(sensorPath))
+ {
+ sensorData[sensorPath] =
+ std::numeric_limits<double>::quiet_NaN();
+ }
continue;
}
@@ -948,22 +955,39 @@
}
}
- dbus::OccDBusSensors::getOccDBus().setValue(
- sensorPath, tempValue * std::pow(10, -3));
+ // If this object path already has a value, only overwite
+ // it if the previous one was an NaN or a smaller value.
+ auto existing = sensorData.find(sensorPath);
+ if (existing != sensorData.end())
+ {
+ if (std::isnan(existing->second) || (tempValue > existing->second))
+ {
+ existing->second = tempValue;
+ }
+ }
+ else
+ {
+ sensorData[sensorPath] = tempValue;
+ }
+ }
- dbus::OccDBusSensors::getOccDBus().setOperationalStatus(sensorPath,
- true);
+ // Now publish the values on D-Bus.
+ for (const auto& [objectPath, value] : sensorData)
+ {
+ dbus::OccDBusSensors::getOccDBus().setValue(objectPath,
+ value * std::pow(10, -3));
- // At this point, the sensor will be created for sure.
- if (existingSensors.find(sensorPath) == existingSensors.end())
+ dbus::OccDBusSensors::getOccDBus().setOperationalStatus(
+ objectPath, !std::isnan(value));
+
+ if (existingSensors.find(objectPath) == existingSensors.end())
{
dbus::OccDBusSensors::getOccDBus().setChassisAssociation(
- sensorPath);
+ objectPath);
}
- existingSensors[sensorPath] = id;
+ existingSensors[objectPath] = id;
}
- return;
}
std::optional<std::string>