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: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
f85b882441
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user