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

Merge branch 'mlxsw-transceiver-trip-points'



Petr Machata says:

====================
mlxsw: Use static trip points for transceiver modules

Ido Schimmel writes:

See patch #1 for motivation and implementation details.

Patches #2-#3 are simple cleanups as a result of the changes in the
first patch.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents dd2d6604 cc19439f
Loading
Loading
Loading
Loading
+36 −129
Original line number Diff line number Diff line
@@ -19,6 +19,9 @@
#define MLXSW_THERMAL_ASIC_TEMP_NORM	75000	/* 75C */
#define MLXSW_THERMAL_ASIC_TEMP_HIGH	85000	/* 85C */
#define MLXSW_THERMAL_ASIC_TEMP_HOT	105000	/* 105C */
#define MLXSW_THERMAL_MODULE_TEMP_NORM	55000	/* 55C */
#define MLXSW_THERMAL_MODULE_TEMP_HIGH	65000	/* 65C */
#define MLXSW_THERMAL_MODULE_TEMP_HOT	80000	/* 80C */
#define MLXSW_THERMAL_HYSTERESIS_TEMP	5000	/* 5C */
#define MLXSW_THERMAL_MODULE_TEMP_SHIFT	(MLXSW_THERMAL_HYSTERESIS_TEMP * 2)
#define MLXSW_THERMAL_MAX_STATE	10
@@ -30,12 +33,6 @@ static char * const mlxsw_thermal_external_allowed_cdev[] = {
	"mlxreg_fan",
};

enum mlxsw_thermal_trips {
	MLXSW_THERMAL_TEMP_TRIP_NORM,
	MLXSW_THERMAL_TEMP_TRIP_HIGH,
	MLXSW_THERMAL_TEMP_TRIP_HOT,
};

struct mlxsw_cooling_states {
	int	min_state;
	int	max_state;
@@ -59,6 +56,24 @@ static const struct thermal_trip default_thermal_trips[] = {
	},
};

static const struct thermal_trip default_thermal_module_trips[] = {
	{	/* In range - 0-40% PWM */
		.type		= THERMAL_TRIP_ACTIVE,
		.temperature	= MLXSW_THERMAL_MODULE_TEMP_NORM,
		.hysteresis	= MLXSW_THERMAL_HYSTERESIS_TEMP,
	},
	{
		/* In range - 40-100% PWM */
		.type		= THERMAL_TRIP_ACTIVE,
		.temperature	= MLXSW_THERMAL_MODULE_TEMP_HIGH,
		.hysteresis	= MLXSW_THERMAL_HYSTERESIS_TEMP,
	},
	{	/* Warning */
		.type		= THERMAL_TRIP_HOT,
		.temperature	= MLXSW_THERMAL_MODULE_TEMP_HOT,
	},
};

static const struct mlxsw_cooling_states default_cooling_states[] = {
	{
		.min_state	= 0,
@@ -140,63 +155,6 @@ static int mlxsw_get_cooling_device_idx(struct mlxsw_thermal *thermal,
	return -ENODEV;
}

static void
mlxsw_thermal_module_trips_reset(struct mlxsw_thermal_module *tz)
{
	tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temperature = 0;
	tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temperature = 0;
	tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temperature = 0;
}

static int
mlxsw_thermal_module_trips_update(struct device *dev, struct mlxsw_core *core,
				  struct mlxsw_thermal_module *tz,
				  int crit_temp, int emerg_temp)
{
	int err;

	/* Do not try to query temperature thresholds directly from the module's
	 * EEPROM if we got valid thresholds from MTMP.
	 */
	if (!emerg_temp || !crit_temp) {
		err = mlxsw_env_module_temp_thresholds_get(core, tz->slot_index,
							   tz->module,
							   SFP_TEMP_HIGH_WARN,
							   &crit_temp);
		if (err)
			return err;

		err = mlxsw_env_module_temp_thresholds_get(core, tz->slot_index,
							   tz->module,
							   SFP_TEMP_HIGH_ALARM,
							   &emerg_temp);
		if (err)
			return err;
	}

	if (crit_temp > emerg_temp) {
		dev_warn(dev, "%s : Critical threshold %d is above emergency threshold %d\n",
			 tz->tzdev->type, crit_temp, emerg_temp);
		return 0;
	}

	/* According to the system thermal requirements, the thermal zones are
	 * defined with three trip points. The critical and emergency
	 * temperature thresholds, provided by QSFP module are set as "active"
	 * and "hot" trip points, "normal" trip point is derived from "active"
	 * by subtracting double hysteresis value.
	 */
	if (crit_temp >= MLXSW_THERMAL_MODULE_TEMP_SHIFT)
		tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temperature = crit_temp -
					MLXSW_THERMAL_MODULE_TEMP_SHIFT;
	else
		tz->trips[MLXSW_THERMAL_TEMP_TRIP_NORM].temperature = crit_temp;
	tz->trips[MLXSW_THERMAL_TEMP_TRIP_HIGH].temperature = crit_temp;
	tz->trips[MLXSW_THERMAL_TEMP_TRIP_HOT].temperature = emerg_temp;

	return 0;
}

static int mlxsw_thermal_bind(struct thermal_zone_device *tzdev,
			      struct thermal_cooling_device *cdev)
{
@@ -325,59 +283,22 @@ static int mlxsw_thermal_module_unbind(struct thermal_zone_device *tzdev,
	return err;
}

static void
mlxsw_thermal_module_temp_and_thresholds_get(struct mlxsw_core *core,
					     u8 slot_index, u16 sensor_index,
					     int *p_temp, int *p_crit_temp,
					     int *p_emerg_temp)
{
	char mtmp_pl[MLXSW_REG_MTMP_LEN];
	int err;

	/* Read module temperature and thresholds. */
	mlxsw_reg_mtmp_pack(mtmp_pl, slot_index, sensor_index,
			    false, false);
	err = mlxsw_reg_query(core, MLXSW_REG(mtmp), mtmp_pl);
	if (err) {
		/* Set temperature and thresholds to zero to avoid passing
		 * uninitialized data back to the caller.
		 */
		*p_temp = 0;
		*p_crit_temp = 0;
		*p_emerg_temp = 0;

		return;
	}
	mlxsw_reg_mtmp_unpack(mtmp_pl, p_temp, NULL, p_crit_temp, p_emerg_temp,
			      NULL);
}

static int mlxsw_thermal_module_temp_get(struct thermal_zone_device *tzdev,
					 int *p_temp)
{
	struct mlxsw_thermal_module *tz = tzdev->devdata;
	struct mlxsw_thermal *thermal = tz->parent;
	int temp, crit_temp, emerg_temp;
	struct device *dev;
	char mtmp_pl[MLXSW_REG_MTMP_LEN];
	u16 sensor_index;
	int err;

	dev = thermal->bus_info->dev;
	sensor_index = MLXSW_REG_MTMP_MODULE_INDEX_MIN + tz->module;

	/* Read module temperature and thresholds. */
	mlxsw_thermal_module_temp_and_thresholds_get(thermal->core,
						     tz->slot_index,
						     sensor_index, &temp,
						     &crit_temp, &emerg_temp);
	*p_temp = temp;

	if (!temp)
		return 0;

	/* Update trip points. */
	mlxsw_thermal_module_trips_update(dev, thermal->core, tz,
					  crit_temp, emerg_temp);

	mlxsw_reg_mtmp_pack(mtmp_pl, tz->slot_index, sensor_index,
			    false, false);
	err = mlxsw_reg_query(thermal->core, MLXSW_REG(mtmp), mtmp_pl);
	if (err)
		return err;
	mlxsw_reg_mtmp_unpack(mtmp_pl, p_temp, NULL, NULL, NULL, NULL);
	return 0;
}

@@ -521,36 +442,26 @@ static void mlxsw_thermal_module_tz_fini(struct thermal_zone_device *tzdev)
	thermal_zone_device_unregister(tzdev);
}

static int
static void
mlxsw_thermal_module_init(struct device *dev, struct mlxsw_core *core,
			  struct mlxsw_thermal *thermal,
			  struct mlxsw_thermal_area *area, u8 module)
{
	struct mlxsw_thermal_module *module_tz;
	int dummy_temp, crit_temp, emerg_temp;
	u16 sensor_index;

	sensor_index = MLXSW_REG_MTMP_MODULE_INDEX_MIN + module;
	module_tz = &area->tz_module_arr[module];
	/* Skip if parent is already set (case of port split). */
	if (module_tz->parent)
		return 0;
		return;
	module_tz->module = module;
	module_tz->slot_index = area->slot_index;
	module_tz->parent = thermal;
	memcpy(module_tz->trips, default_thermal_trips,
	BUILD_BUG_ON(ARRAY_SIZE(default_thermal_module_trips) !=
		     MLXSW_THERMAL_NUM_TRIPS);
	memcpy(module_tz->trips, default_thermal_module_trips,
	       sizeof(thermal->trips));
	memcpy(module_tz->cooling_states, default_cooling_states,
	       sizeof(thermal->cooling_states));
	/* Initialize all trip point. */
	mlxsw_thermal_module_trips_reset(module_tz);
	/* Read module temperature and thresholds. */
	mlxsw_thermal_module_temp_and_thresholds_get(core, area->slot_index,
						     sensor_index, &dummy_temp,
						     &crit_temp, &emerg_temp);
	/* Update trip point according to the module data. */
	return mlxsw_thermal_module_trips_update(dev, core, module_tz,
						 crit_temp, emerg_temp);
}

static void mlxsw_thermal_module_fini(struct mlxsw_thermal_module *module_tz)
@@ -589,11 +500,8 @@ mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core,
	if (!area->tz_module_arr)
		return -ENOMEM;

	for (i = 0; i < area->tz_module_num; i++) {
		err = mlxsw_thermal_module_init(dev, core, thermal, area, i);
		if (err)
			goto err_thermal_module_init;
	}
	for (i = 0; i < area->tz_module_num; i++)
		mlxsw_thermal_module_init(dev, core, thermal, area, i);

	for (i = 0; i < area->tz_module_num; i++) {
		module_tz = &area->tz_module_arr[i];
@@ -607,7 +515,6 @@ mlxsw_thermal_modules_init(struct device *dev, struct mlxsw_core *core,
	return 0;

err_thermal_module_tz_init:
err_thermal_module_init:
	for (i = area->tz_module_num - 1; i >= 0; i--)
		mlxsw_thermal_module_fini(&area->tz_module_arr[i]);
	kfree(area->tz_module_arr);