Merge branch 'mlxsw-Expose-critical-and-emergency-module-alarms'

Ido Schimmel says:

====================
mlxsw: Expose critical and emergency module alarms

Amit says:

Extend hwmon interface with critical and emergency module alarms.

In case that current module temperature is higher than emergency
threshold, EMERGENCY alarm will be reported in sensors utility:

$ sensors
...
front panel 025:  +55.0°C  (crit = +35.0°C, emerg = +40.0°C) ALARM(EMERGENCY)

In case that current module temperature is higher than critical
threshold, CRIT alarm will be reported in sensors utility:

$ sensors
...
front panel 025:  +54.0°C  (crit = +35.0°C, emerg = +80.0°C) ALARM(CRIT)

Patch set overview:

Patches #1-#2 make several changes to make the code easier to change.

Patch #3 extends the hwmon interface with the new module alarms.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2020-09-03 12:12:05 -07:00
commit ffd923f5f8

View File

@ -12,8 +12,17 @@
#include "core.h"
#include "core_env.h"
#define MLXSW_HWMON_TEMP_SENSOR_MAX_COUNT 127
#define MLXSW_HWMON_ATTR_COUNT (MLXSW_HWMON_TEMP_SENSOR_MAX_COUNT * 4 + \
#define MLXSW_HWMON_SENSORS_MAX_COUNT 64
#define MLXSW_HWMON_MODULES_MAX_COUNT 64
#define MLXSW_HWMON_GEARBOXES_MAX_COUNT 32
#define MLXSW_HWMON_ATTR_PER_SENSOR 3
#define MLXSW_HWMON_ATTR_PER_MODULE 7
#define MLXSW_HWMON_ATTR_PER_GEARBOX 4
#define MLXSW_HWMON_ATTR_COUNT (MLXSW_HWMON_SENSORS_MAX_COUNT * MLXSW_HWMON_ATTR_PER_SENSOR + \
MLXSW_HWMON_MODULES_MAX_COUNT * MLXSW_HWMON_ATTR_PER_MODULE + \
MLXSW_HWMON_GEARBOXES_MAX_COUNT * MLXSW_HWMON_ATTR_PER_GEARBOX + \
MLXSW_MFCR_TACHOS_MAX + MLXSW_MFCR_PWMS_MAX)
struct mlxsw_hwmon_attr {
@ -205,25 +214,39 @@ static ssize_t mlxsw_hwmon_pwm_store(struct device *dev,
return len;
}
static ssize_t mlxsw_hwmon_module_temp_show(struct device *dev,
struct device_attribute *attr,
char *buf)
static int mlxsw_hwmon_module_temp_get(struct device *dev,
struct device_attribute *attr,
int *p_temp)
{
struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
char mtmp_pl[MLXSW_REG_MTMP_LEN];
u8 module;
int temp;
int err;
module = mlwsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count;
mlxsw_reg_mtmp_pack(mtmp_pl, MLXSW_REG_MTMP_MODULE_INDEX_MIN + module,
false, false);
err = mlxsw_reg_query(mlxsw_hwmon->core, MLXSW_REG(mtmp), mtmp_pl);
if (err) {
dev_err(dev, "Failed to query module temperature\n");
return err;
}
mlxsw_reg_mtmp_unpack(mtmp_pl, p_temp, NULL, NULL);
return 0;
}
static ssize_t mlxsw_hwmon_module_temp_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
int err, temp;
err = mlxsw_hwmon_module_temp_get(dev, attr, &temp);
if (err)
return err;
mlxsw_reg_mtmp_unpack(mtmp_pl, &temp, NULL, NULL);
return sprintf(buf, "%d\n", temp);
}
@ -270,47 +293,71 @@ static ssize_t mlxsw_hwmon_module_temp_fault_show(struct device *dev,
return sprintf(buf, "%u\n", fault);
}
static ssize_t
mlxsw_hwmon_module_temp_critical_show(struct device *dev,
struct device_attribute *attr, char *buf)
static int mlxsw_hwmon_module_temp_critical_get(struct device *dev,
struct device_attribute *attr,
int *p_temp)
{
struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
int temp;
u8 module;
int err;
module = mlwsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count;
err = mlxsw_env_module_temp_thresholds_get(mlxsw_hwmon->core, module,
SFP_TEMP_HIGH_WARN, &temp);
SFP_TEMP_HIGH_WARN, p_temp);
if (err) {
dev_err(dev, "Failed to query module temperature thresholds\n");
return err;
}
return 0;
}
static ssize_t
mlxsw_hwmon_module_temp_critical_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int err, temp;
err = mlxsw_hwmon_module_temp_critical_get(dev, attr, &temp);
if (err)
return err;
return sprintf(buf, "%u\n", temp);
}
static int mlxsw_hwmon_module_temp_emergency_get(struct device *dev,
struct device_attribute *attr,
int *p_temp)
{
struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
u8 module;
int err;
module = mlwsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count;
err = mlxsw_env_module_temp_thresholds_get(mlxsw_hwmon->core, module,
SFP_TEMP_HIGH_ALARM, p_temp);
if (err) {
dev_err(dev, "Failed to query module temperature thresholds\n");
return err;
}
return 0;
}
static ssize_t
mlxsw_hwmon_module_temp_emergency_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct mlxsw_hwmon_attr *mlwsw_hwmon_attr =
container_of(attr, struct mlxsw_hwmon_attr, dev_attr);
struct mlxsw_hwmon *mlxsw_hwmon = mlwsw_hwmon_attr->hwmon;
u8 module;
int temp;
int err;
int err, temp;
module = mlwsw_hwmon_attr->type_index - mlxsw_hwmon->sensor_count;
err = mlxsw_env_module_temp_thresholds_get(mlxsw_hwmon->core, module,
SFP_TEMP_HIGH_ALARM, &temp);
if (err) {
dev_err(dev, "Failed to query module temperature thresholds\n");
err = mlxsw_hwmon_module_temp_emergency_get(dev, attr, &temp);
if (err)
return err;
}
return sprintf(buf, "%u\n", temp);
}
@ -341,6 +388,53 @@ mlxsw_hwmon_gbox_temp_label_show(struct device *dev,
return sprintf(buf, "gearbox %03u\n", index);
}
static ssize_t mlxsw_hwmon_temp_critical_alarm_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
int err, temp, emergency_temp, critic_temp;
err = mlxsw_hwmon_module_temp_get(dev, attr, &temp);
if (err)
return err;
if (temp <= 0)
return sprintf(buf, "%d\n", false);
err = mlxsw_hwmon_module_temp_emergency_get(dev, attr, &emergency_temp);
if (err)
return err;
if (temp >= emergency_temp)
return sprintf(buf, "%d\n", false);
err = mlxsw_hwmon_module_temp_critical_get(dev, attr, &critic_temp);
if (err)
return err;
return sprintf(buf, "%d\n", temp >= critic_temp);
}
static ssize_t mlxsw_hwmon_temp_emergency_alarm_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
int err, temp, emergency_temp;
err = mlxsw_hwmon_module_temp_get(dev, attr, &temp);
if (err)
return err;
if (temp <= 0)
return sprintf(buf, "%d\n", false);
err = mlxsw_hwmon_module_temp_emergency_get(dev, attr, &emergency_temp);
if (err)
return err;
return sprintf(buf, "%d\n", temp >= emergency_temp);
}
enum mlxsw_hwmon_attr_type {
MLXSW_HWMON_ATTR_TYPE_TEMP,
MLXSW_HWMON_ATTR_TYPE_TEMP_MAX,
@ -354,6 +448,8 @@ enum mlxsw_hwmon_attr_type {
MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_EMERG,
MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_LABEL,
MLXSW_HWMON_ATTR_TYPE_TEMP_GBOX_LABEL,
MLXSW_HWMON_ATTR_TYPE_TEMP_CRIT_ALARM,
MLXSW_HWMON_ATTR_TYPE_TEMP_EMERGENCY_ALARM,
};
static void mlxsw_hwmon_attr_add(struct mlxsw_hwmon *mlxsw_hwmon,
@ -444,6 +540,20 @@ static void mlxsw_hwmon_attr_add(struct mlxsw_hwmon *mlxsw_hwmon,
snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
"temp%u_label", num + 1);
break;
case MLXSW_HWMON_ATTR_TYPE_TEMP_CRIT_ALARM:
mlxsw_hwmon_attr->dev_attr.show =
mlxsw_hwmon_temp_critical_alarm_show;
mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
"temp%u_crit_alarm", num + 1);
break;
case MLXSW_HWMON_ATTR_TYPE_TEMP_EMERGENCY_ALARM:
mlxsw_hwmon_attr->dev_attr.show =
mlxsw_hwmon_temp_emergency_alarm_show;
mlxsw_hwmon_attr->dev_attr.attr.mode = 0444;
snprintf(mlxsw_hwmon_attr->name, sizeof(mlxsw_hwmon_attr->name),
"temp%u_emergency_alarm", num + 1);
break;
default:
WARN_ON(1);
}
@ -566,6 +676,12 @@ static int mlxsw_hwmon_module_init(struct mlxsw_hwmon *mlxsw_hwmon)
mlxsw_hwmon_attr_add(mlxsw_hwmon,
MLXSW_HWMON_ATTR_TYPE_TEMP_MODULE_LABEL,
i, i);
mlxsw_hwmon_attr_add(mlxsw_hwmon,
MLXSW_HWMON_ATTR_TYPE_TEMP_CRIT_ALARM,
i, i);
mlxsw_hwmon_attr_add(mlxsw_hwmon,
MLXSW_HWMON_ATTR_TYPE_TEMP_EMERGENCY_ALARM,
i, i);
}
return 0;