Commit ffd923f5 authored by David S. Miller's avatar David S. Miller
Browse files

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: default avatarDavid S. Miller <davem@davemloft.net>
parents 7544abd9 91df5d3a
Loading
Loading
Loading
Loading
+134 −18
Original line number Diff line number Diff line
@@ -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,
static int mlxsw_hwmon_module_temp_get(struct device *dev,
				       struct device_attribute *attr,
					    char *buf)
				       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,48 +293,72 @@ 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 sprintf(buf, "%u\n", temp);
	return 0;
}

static ssize_t
mlxsw_hwmon_module_temp_emergency_show(struct device *dev,
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,
				       char *buf)
						 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 temp;
	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, &temp);
						   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)
{
	int err, temp;

	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;