[PATCH net-next 5/6] eth: fbnic: report temperature and voltage alarms via hwmon
From: Zinc Lim
Date: Tue Jul 21 2026 - 19:13:51 EST
Building on the temperature and voltage thresholds stored in
fbnic_fw_cap, expose alarm attributes through the hwmon interface:
temp1_{min,max,crit}_alarm and in0_{min,max}_alarm.
Each alarm is computed by taking a live sensor reading and comparing it
against the corresponding stored threshold. The static thresholds
(min/max/crit) are returned first straight from fbnic_fw_cap without a
firmware round-trip, and unsupported attributes are rejected up front, so
only attributes that actually need a live value fall through to a single
sensor read that then feeds input and every alarm.
A threshold the firmware did not populate reports -ENODATA for both the
threshold attribute and its alarm.
Signed-off-by: Zinc Lim <limzhineng2@xxxxxxxxx>
---
drivers/net/ethernet/meta/fbnic/fbnic_hwmon.c | 68 +++++++++++++++++--
1 file changed, 61 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_hwmon.c b/drivers/net/ethernet/meta/fbnic/fbnic_hwmon.c
index 4938f7b39140..c5cddd9cef12 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_hwmon.c
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_hwmon.c
@@ -87,34 +87,84 @@ static int fbnic_hwmon_read_threshold(long thr, long *val)
return 0;
}
+static int fbnic_hwmon_read_alarm(long a, long b, long *val)
+{
+ if (a == FBNIC_SENSOR_NO_DATA || b == FBNIC_SENSOR_NO_DATA)
+ return -ENODATA;
+
+ *val = a >= b;
+ return 0;
+}
+
static int fbnic_hwmon_temp_read(struct fbnic_dev *fbd, u32 attr, long *val)
{
+ int err;
+
switch (attr) {
- case hwmon_temp_input:
- return fbnic_hwmon_sensor_read(fbd, FBNIC_SENSOR_TEMP, val);
case hwmon_temp_min:
return fbnic_hwmon_read_threshold(fbd->fw_cap.temp.min, val);
case hwmon_temp_max:
return fbnic_hwmon_read_threshold(fbd->fw_cap.temp.max, val);
case hwmon_temp_crit:
return fbnic_hwmon_read_threshold(fbd->fw_cap.temp.crit, val);
+ case hwmon_temp_input:
+ case hwmon_temp_min_alarm:
+ case hwmon_temp_max_alarm:
+ case hwmon_temp_crit_alarm:
+ break;
default:
return -EOPNOTSUPP;
}
+
+ err = fbnic_hwmon_sensor_read(fbd, FBNIC_SENSOR_TEMP, val);
+ if (err)
+ return err;
+
+ switch (attr) {
+ case hwmon_temp_input:
+ return 0;
+ case hwmon_temp_min_alarm:
+ return fbnic_hwmon_read_alarm(fbd->fw_cap.temp.min, *val, val);
+ case hwmon_temp_max_alarm:
+ return fbnic_hwmon_read_alarm(*val, fbd->fw_cap.temp.max, val);
+ case hwmon_temp_crit_alarm:
+ return fbnic_hwmon_read_alarm(*val, fbd->fw_cap.temp.crit, val);
+ }
+
+ return -EOPNOTSUPP;
}
static int fbnic_hwmon_in_read(struct fbnic_dev *fbd, u32 attr, long *val)
{
+ int err;
+
switch (attr) {
- case hwmon_in_input:
- return fbnic_hwmon_sensor_read(fbd, FBNIC_SENSOR_VOLTAGE, val);
case hwmon_in_min:
return fbnic_hwmon_read_threshold(fbd->fw_cap.volt.min, val);
case hwmon_in_max:
return fbnic_hwmon_read_threshold(fbd->fw_cap.volt.max, val);
+ case hwmon_in_input:
+ case hwmon_in_min_alarm:
+ case hwmon_in_max_alarm:
+ break;
default:
return -EOPNOTSUPP;
}
+
+ err = fbnic_hwmon_sensor_read(fbd, FBNIC_SENSOR_VOLTAGE, val);
+ if (err)
+ return err;
+
+ switch (attr) {
+ case hwmon_in_input:
+ return 0;
+ case hwmon_in_min_alarm:
+ return fbnic_hwmon_read_alarm(fbd->fw_cap.volt.min, *val, val);
+ case hwmon_in_max_alarm:
+ return fbnic_hwmon_read_alarm(*val, fbd->fw_cap.volt.max, val);
+ }
+
+ return -EOPNOTSUPP;
}
static int fbnic_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
@@ -139,10 +189,14 @@ static const struct hwmon_ops fbnic_hwmon_ops = {
static const struct hwmon_channel_info *fbnic_hwmon_info[] = {
HWMON_CHANNEL_INFO(temp,
- HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX |
- HWMON_T_CRIT),
+ HWMON_T_INPUT |
+ HWMON_T_MIN | HWMON_T_MIN_ALARM |
+ HWMON_T_MAX | HWMON_T_MAX_ALARM |
+ HWMON_T_CRIT | HWMON_T_CRIT_ALARM),
HWMON_CHANNEL_INFO(in,
- HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX),
+ HWMON_I_INPUT |
+ HWMON_I_MIN | HWMON_I_MIN_ALARM |
+ HWMON_I_MAX | HWMON_I_MAX_ALARM),
NULL
};
--
2.53.0-Meta