Files
2026-04-23 17:07:55 +08:00

502 lines
16 KiB
Diff
Executable File

From 80cb5c7e022af367dd17981f2a0ffe7d5cf4052a Mon Sep 17 00:00:00 2001
From: "Wang.Bin" <Bin-B.Wang@luxshare-ict.com>
Date: Wed, 20 Nov 2024 19:14:14 +0800
Subject: [PATCH 4/4] Support discrete generic sensors
---
fault-monitor/fru-fault-monitor.cpp | 393 ++++++++++++++++++++++++++--
fault-monitor/fru-fault-monitor.hpp | 3 +-
2 files changed, 379 insertions(+), 17 deletions(-)
diff --git a/fault-monitor/fru-fault-monitor.cpp b/fault-monitor/fru-fault-monitor.cpp
index aa7b8cc..737c90d 100644
--- a/fault-monitor/fru-fault-monitor.cpp
+++ b/fault-monitor/fru-fault-monitor.cpp
@@ -69,6 +69,37 @@ using InvalidArgumentErr =
constexpr const char* discreteSensorNs = "No state defined";
+enum AlarmType : uint64_t
+{
+ NORMAL = 0,
+ NONCRITICAL = 1,
+ CRITICAL = 2,
+ NONRECOV = 4,
+};
+
+/*alarms bits: nr, nc, c*/
+constexpr auto ALARM_BIT_NUM = 3;
+constexpr auto ALARM_ALL_BITS = NONCRITICAL | CRITICAL | NONRECOV;
+constexpr uint64_t ALARM_STATUS_MASK_NR = 0x4924924924924924;
+constexpr uint64_t ALARM_STATUS_MASK_C = 0x2492492492492492;
+constexpr uint64_t ALARM_STATUS_MASK_NC = 0x1249249249249249;
+
+/*discrete generic offset*/
+
+constexpr auto EVENT_TYPE_03H_STATE_DEASSERT = 0;
+constexpr auto EVENT_TYPE_03H_STATE_ASSERT = 1;
+
+constexpr auto EVENT_TYPE_07H_TRANSITION_TO_OK = 0;
+constexpr auto EVENT_TYPE_07H_TRANSITION_TO_NC_FROM_OK = 1;
+
+constexpr auto EVENT_TYPE_08H_ABSENT = 0;
+constexpr auto EVENT_TYPE_08H_PRESENT = 1;
+
+constexpr auto EVENT_TYPE_0BH_FULLY_REDUNDANT = 0;
+constexpr auto EVENT_TYPE_0BH_REDUNDANT_LOST = 1;
+
+/*discrete sensor specific offset*/
+
/*discrete sensor specific offset*/
// 07H
constexpr auto IPMI_CPU_IERR = 0;
@@ -164,16 +195,8 @@ constexpr auto FIRMWARE_UPDATE_SUCCESS = 7;
/*sensor object, SensorStatusInfo*/
std::unordered_map<std::string, SensorStatusInfo> sensorStatusRec;
-std::unordered_map<std::string, std::unordered_map<uint8_t, DriveStatus>> driveStatusRec;
-
-
-enum AlarmType
-{
- NORMAL = 0,
- NONCRITICAL = 1,
- CRITICAL = 2,
- NONRECOV = 4,
-};
+std::unordered_map<std::string, std::unordered_map<uint8_t, SensorStatus>> driveStatusRec;
+std::unordered_map<uint8_t, SensorStatus> powerFaultStatusRec;
struct SelSeverityInfo
{
@@ -204,6 +227,30 @@ using sensorCodes = std::vector<uint8_t>;
using ipmiSensorsInfo = std::unordered_map<std::string, sensorCodes>;
std::optional<ipmiSensorsInfo> ipmiSensors;
+const std::unordered_map<uint8_t, discrectSensorEvent> genericEventTypes{
+ {0x03,
+ {
+ {EVENT_TYPE_03H_STATE_DEASSERT, "State Deasserted"},
+ {EVENT_TYPE_03H_STATE_ASSERT, "State Asserted"},
+ }},
+ {0x07,
+ {
+ {EVENT_TYPE_07H_TRANSITION_TO_OK, "Transition to OK"},
+ {EVENT_TYPE_07H_TRANSITION_TO_NC_FROM_OK,
+ "Transition to Non-critical from OK"},
+ }},
+ {0x08,
+ {
+ {EVENT_TYPE_08H_ABSENT, "Device Absent"},
+ {EVENT_TYPE_08H_PRESENT, "Device Present"},
+ }},
+ {0x0B,
+ {
+ {EVENT_TYPE_0BH_FULLY_REDUNDANT, "Fully Redundant"},
+ {EVENT_TYPE_0BH_REDUNDANT_LOST, "Redundancy Lost"},
+ }},
+};
+
const std::unordered_map<SensorType, discrectSensorEvent> sensorSpecificTypes{
{SENSOR_TYPE_PROCESSOR,
{
@@ -316,6 +363,15 @@ const std::unordered_map<SensorType, discrectSensorEvent> sensorSpecificTypes{
}},
};
+static const std::unordered_map<std::string, std::vector<uint8_t>>
+ flipStateSel = {
+ {"Redundant_PSU",
+ {EVENT_TYPE_0BH_FULLY_REDUNDANT, EVENT_TYPE_0BH_REDUNDANT_LOST}},
+ {"SYS_FAN_Status",
+ {EVENT_TYPE_07H_TRANSITION_TO_OK,
+ EVENT_TYPE_07H_TRANSITION_TO_NC_FROM_OK}},
+};
+
std::optional<ipmiSensorsInfo> initIPMISensorInfo(sdbusplus::bus::bus& bus)
{
constexpr auto service = "xyz.openbmc_project.Ipmi.Host";
@@ -557,13 +613,192 @@ enum
{
UNSPECIFY_SENSOR_TYPE = 0x00,
THRESHOLD_SENSOR_TYPE = 0x01,
- GENERIC_S_SENSOR_TYPE = 0x02,
- GENERIC_E_SENSOR_TYPE = 0x0C,
+ GENERIC_START_SENSOR_TYPE = 0x02,
+ GENERIC_END_SENSOR_TYPE = 0x0C,
SPECIFIC_SENSOR_TYPE = 0x6F,
- OEM_S_SENSOR_TYPE = 0x70,
- OEM_E_SENSOR_TYPE = 0x7F
+ OEM_START_SENSOR_TYPE = 0x70,
+ OEM_END_SENSOR_TYPE = 0x7F
+};
+
+inline void recordAlarmStatus(const std::string& sensorPath,
+ AlarmType alarmStatus, int evOffset, int ed,
+ bool assertAlarm,
+ const bool& isGenericDiscreteSensor)
+{
+ uint64_t statusBit = static_cast<uint64_t>(alarmStatus);
+
+ std::string sensorName{sensorPath};
+ size_t lastPos = sensorPath.find_last_of('/');
+ if (lastPos != std::string::npos)
+ {
+ // Get sensor name from the sensor full path
+ sensorName = sensorPath.substr(lastPos + 1);
+ }
+
+ if (assertAlarm)
+ {
+ if (ed != 0)
+ {
+ sensorStatusRec[sensorPath].alarmStatus |=
+ statusBit << (evOffset * ALARM_BIT_NUM);
+
+ auto it = flipStateSel.find(sensorName);
+ if (it != flipStateSel.end())
+ {
+ auto eventOffsets = it->second;
+ auto targetIt = std::find(eventOffsets.begin(),
+ eventOffsets.begin(), evOffset);
+ if (targetIt != eventOffsets.end())
+ {
+ for (const auto& offset : eventOffsets)
+ {
+ if (offset == evOffset)
+ {
+ continue;
+ }
+ sensorStatusRec[sensorPath].alarmStatus &=
+ ~(statusBit << (offset * ALARM_BIT_NUM));
+ }
+ }
+ }
+ }
+ else
+ {
+ sensorStatusRec[sensorPath].alarmStatus &=
+ ~(statusBit << (evOffset * ALARM_BIT_NUM));
+ }
+ }
+ else
+ {
+ if (ed != 0)
+ {
+ sensorStatusRec[sensorPath].alarmStatus &=
+ ~(statusBit << (evOffset * ALARM_BIT_NUM));
+
+ auto it = flipStateSel.find(sensorName);
+ if (it != flipStateSel.end())
+ {
+ auto eventOffsets = it->second;
+ auto targetIt = std::find(eventOffsets.begin(),
+ eventOffsets.end(), evOffset);
+ if (targetIt != eventOffsets.end())
+ {
+ for (const auto& offset : eventOffsets)
+ {
+ if (offset == evOffset)
+ {
+ continue;
+ }
+ sensorStatusRec[sensorPath].alarmStatus &=
+ ~(statusBit << (offset * ALARM_BIT_NUM));
+ }
+ }
+ }
+ }
+ else
+ {
+ sensorStatusRec[sensorPath].alarmStatus |=
+ statusBit << (evOffset * ALARM_BIT_NUM);
+ }
+ }
+
+ if (isGenericDiscreteSensor)
+ {
+ if (ed != 0)
+ {
+ // Generic discrete sensor's events are mutually exclusive,
+ // and at the same time, only one bit of 'sensorStatus' will be set,
+ // so there is '=', not '|='
+ sensorStatusRec[sensorPath].sensorStatus = 1 << evOffset;
+ }
+ else
+ {
+ sensorStatusRec[sensorPath].sensorStatus &= ~(1 << evOffset);
+ }
+ }
+ else
+ {
+ if (ed != 0)
+ {
+ sensorStatusRec[sensorPath].sensorStatus |= 1 << evOffset;
+ }
+ else
+ {
+ sensorStatusRec[sensorPath].sensorStatus &= ~(1 << evOffset);
+ }
+ }
+}
+
+/*record led status and entity manager status*/
+inline void recordAlarmStatus(SensorStatus& statusRec,
+ const AlarmType& alarmStatus, const int& evOffset,
+ const int& ed, const bool& assertAlarm,
+ const bool& isGenericDiscreteSensor)
+{
+ uint64_t statusBit = static_cast<uint64_t>(alarmStatus);
+ if (assertAlarm)
+ {
+ if (ed)
+ {
+ statusRec.alarmStatus |= statusBit << (evOffset * ALARM_BIT_NUM);
+ }
+ else
+ {
+ statusRec.alarmStatus &= ~(statusBit << (evOffset * ALARM_BIT_NUM));
+ }
+ }
+ else
+ {
+ if (ed)
+ {
+ statusRec.alarmStatus &= ~(statusBit << (evOffset * ALARM_BIT_NUM));
+ }
+ else
+ {
+ statusRec.alarmStatus |= statusBit << (evOffset * ALARM_BIT_NUM);
+ }
+ }
+
+ if (isGenericDiscreteSensor)
+ {
+ if (ed)
+ {
+ // Generic discrete sensor's events are mutually exclusive,
+ // and at the same time, only one bit of 'sensorStatus' will be set,
+ // so there is '=', not '|='
+ statusRec.sensorStatus = 1 << evOffset;
+ }
+ else
+ {
+ statusRec.sensorStatus &= ~(1 << evOffset);
+ }
+ }
+ else
+ {
+ if (ed)
+ {
+ statusRec.sensorStatus |= 1 << evOffset;
+ }
+ else
+ {
+ statusRec.sensorStatus &= ~(1 << evOffset);
+ }
+ }
+}
+
+enum
+{
+ SYSTEM_FIRMWARE_ERROR_INDEX_START = 0x00,
+ SYSTEM_FIRMWARE_ERROR_INDEX_END = 0x0D,
+};
+
+enum
+{
+ POWER_FAULT_START_EVENT_INDEX = 0x00,
+ POWER_FAULT_END_EVENT_INDEX = 0x08,
};
+
void fillSensorDescription(const std::string& sensorPath, int eventOffset)
{
sensorStatusRec[sensorPath].description = discreteSensorNs;
@@ -599,6 +834,7 @@ void fillSensorDescription(const std::string& sensorPath, int eventOffset)
//}
}
+
void parseSpecificSensorSelSeverity(sdbusplus::bus::bus& bus,
const std::string& sensorPath,
const SensorType& sensorType,
@@ -698,6 +934,109 @@ void parseSpecificSensorSelSeverity(sdbusplus::bus::bus& bus,
return;
}
+void powerFaultRecAlarmStatus(const std::string& sensorPath)
+{
+ uint16_t sensorStatus = 0;
+ uint64_t alarmStatus = 0;
+ constexpr uint64_t eventType03hStateMask =
+ (1 << EVENT_TYPE_03H_STATE_DEASSERT) |
+ (1 << EVENT_TYPE_03H_STATE_ASSERT);
+
+ for (const auto& [evIndex, status] : powerFaultStatusRec)
+ {
+ sensorStatus |= (status.sensorStatus & eventType03hStateMask);
+ /*only need to record an alarm on bit0-bit2*/
+ uint64_t alarm = status.alarmStatus;
+ if (ALARM_STATUS_MASK_C & alarm)
+ {
+ alarmStatus |= CRITICAL;
+ }
+ else if (ALARM_STATUS_MASK_NR & alarm)
+ {
+ alarmStatus |= NONRECOV;
+ }
+ else if (ALARM_STATUS_MASK_NC & alarm)
+ {
+ alarmStatus |= NONCRITICAL;
+ }
+ }
+
+ sensorStatusRec[sensorPath].sensorStatus = sensorStatus;
+ sensorStatusRec[sensorPath].alarmStatus = alarmStatus;
+}
+
+struct AlarmAction
+{
+ AlarmType alarmStatus;
+ bool assertToAlarm; /*true: assert to alarm; false: deassert to alarm*/
+};
+
+/*event offset, action*/
+using EventActions = std::unordered_map<uint8_t, AlarmAction>;
+
+/*event type, all actions*/
+using EventAlarm = std::unordered_map<uint8_t, EventActions>;
+
+ void parseDiscreteGenericSelSeverity(
+ sdbusplus::bus::bus& bus, const std::string& sensorPath,
+ const SensorType& sensorType, const uint8_t& eventType,
+ const std::string& eventData, const std::string& eventDir,
+ const AlarmType& severity, const bool& assertToAlarm)
+{
+ // The sensorStatusRec[sensorPath] obj will be created when init the
+ // 'Status'. See: initDiscreteSensorStatusInfo() and sensorMatchHandler().
+ // If true, it means that the 'Status' has been initialized
+ // and the status sensor object on the entity-manager has been created.
+
+ // if (sensorStatusRec.find(sensorPath) == sensorStatusRec.end())
+ // {
+ // lg2::error(
+ // "sensorPath not found in sensorStatusRec: {PATH}, add sensorPath into getPathfailedRec",
+ // "PATH", sensorPath);
+ // SelSeverityInfo severityInfo(sensorPath, sensorType, eventType,
+ // eventData, eventDir, severity,
+ // assertToAlarm);
+ // getPathfailedRec[sensorPath].push_back(severityInfo);
+ // return;
+ // }
+
+ std::string eventData1 = eventData.substr(0, 2);
+ int ev = std::stol(eventData1, nullptr, 16);
+ int ed = std::stol(eventDir);
+ int ev1Offset = ev & SENSOR_EVENT_DATA1_EVENT_OFFSET;
+
+ if (sensorType != SENSOR_TYPE_POWER_FAULT)
+ {
+ recordAlarmStatus(sensorPath, severity, ev1Offset, ed, assertToAlarm,
+ true);
+ }
+ else
+ {
+ std::string eventData2 = eventData.substr(2, 2);
+ int ev2Index = std::stol(eventData2, nullptr, 16);
+
+ if (ev2Index < POWER_FAULT_START_EVENT_INDEX ||
+ ev2Index > POWER_FAULT_END_EVENT_INDEX)
+ {
+ lg2::error("Invalid event index = {INDEX}", "INDEX", ev2Index);
+ return;
+ }
+
+ recordAlarmStatus(powerFaultStatusRec[ev2Index], severity, ev1Offset,
+ ed, assertToAlarm, true);
+ powerFaultRecAlarmStatus(sensorPath);
+ }
+
+ sensorStatusRec[sensorPath].eventType = eventType;
+ sensorStatusRec[sensorPath].sensorType = sensorType;
+
+ setDiscreteSensorStatusValue(bus, sensorPath, eventData);
+
+ //updateSensorStatus(bus, sensorPath);
+
+ //controlHealthLed(bus);
+}
+
void Add::filterSEL(sdbusplus::bus::bus& bus, const std::string& path)
{
//AlarmType severity = NORMAL;
@@ -728,7 +1067,9 @@ void Add::filterSEL(sdbusplus::bus::bus& bus, const std::string& path)
uint8_t typeCode = 0;
uint8_t sensorType = 0;
- std::string sensorData, sensorPath, eventDir;
+ std::string sensorData, sensorPath, eventDir, assertAlarm;
+ bool assertToAlarm;
+ AlarmType confSeverity = AlarmType::NORMAL;
for (auto& item : additionalDatas)
{
std::string::size_type nStr;
@@ -760,6 +1101,16 @@ void Add::filterSEL(sdbusplus::bus::bus& bus, const std::string& path)
std::cerr << "sensorPath " << sensorPath <<"\n";
}
}
+
+ if (assertAlarm.empty())
+ {
+ nStr = item.find("ASSERT_ALARM=");
+ if (std::string::npos != nStr)
+ {
+ assertAlarm = item.substr(nStr + strlen("ASSERT_ALARM="));
+ assertToAlarm = std::stol(assertAlarm, nullptr, 10);
+ }
+ }
}
if (!ipmiSensors)
@@ -795,9 +1146,19 @@ void Add::filterSEL(sdbusplus::bus::bus& bus, const std::string& path)
else if (typeCode == SPECIFIC_SENSOR_TYPE)
{
// discrete
- parseSpecificSensorSelSeverity(
+ parseSpecificSensorSelSeverity(
bus, sensorPath, static_cast<SensorType>(sensorType), sensorData,
eventDir);
+ }else if (typeCode >= GENERIC_START_SENSOR_TYPE &&
+ typeCode <= GENERIC_END_SENSOR_TYPE)
+ {
+ parseDiscreteGenericSelSeverity(
+ bus, sensorPath, static_cast<SensorType>(sensorType), typeCode,
+ sensorData, eventDir, confSeverity, assertToAlarm);
+ }
+ else
+ {
+ return;
}
//controlHealthLed(bus);
diff --git a/fault-monitor/fru-fault-monitor.hpp b/fault-monitor/fru-fault-monitor.hpp
index bd4a852..0dacc0c 100644
--- a/fault-monitor/fru-fault-monitor.hpp
+++ b/fault-monitor/fru-fault-monitor.hpp
@@ -118,9 +118,10 @@ struct SensorStatusInfo
uint16_t sensorStatus;
uint64_t alarmStatus;
std::string description; // add description for discrete sensor
+ uint8_t sdrType; // Only for discrete sensors
};
-struct DriveStatus
+struct SensorStatus
{
uint16_t sensorStatus; /*entity status*/
uint64_t alarmStatus; /*alarm status*/
--
2.25.1