diff options
author | Amit Cohen <amcohen@nvidia.com> | 2020-09-27 10:50:12 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2020-09-27 23:27:01 +0300 |
commit | f21b1a646f812ccc2e56f0d5c804b64f0043ea78 (patch) | |
tree | 80a86c135193ee7f47bee7548bd30272ccb75f0b /drivers | |
parent | 943585c9eec32135750226e42d3c3510f079bd5e (diff) | |
download | linux-f21b1a646f812ccc2e56f0d5c804b64f0043ea78.tar.xz |
mlxsw: Enable temperature event for all supported port module sensors
MTWE (Management Temperature Warning Event) is triggered for sensors
whose temperature event enable bit is enabled in the MTMP register.
Enable events for all the modules that have a temperature sensor.
Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/core_env.c | 99 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/reg.h | 8 |
2 files changed, 107 insertions, 0 deletions
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c index 06c04175878b..63dd1fb58381 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c @@ -306,6 +306,99 @@ int mlxsw_env_get_module_eeprom(struct net_device *netdev, } EXPORT_SYMBOL(mlxsw_env_get_module_eeprom); +static int mlxsw_env_module_has_temp_sensor(struct mlxsw_core *mlxsw_core, + u8 module, + bool *p_has_temp_sensor) +{ + char mtbr_pl[MLXSW_REG_MTBR_LEN]; + u16 temp; + int err; + + mlxsw_reg_mtbr_pack(mtbr_pl, MLXSW_REG_MTBR_BASE_MODULE_INDEX + module, + 1); + err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mtbr), mtbr_pl); + if (err) + return err; + + mlxsw_reg_mtbr_temp_unpack(mtbr_pl, 0, &temp, NULL); + + switch (temp) { + case MLXSW_REG_MTBR_BAD_SENS_INFO: + case MLXSW_REG_MTBR_NO_CONN: + case MLXSW_REG_MTBR_NO_TEMP_SENS: + case MLXSW_REG_MTBR_INDEX_NA: + *p_has_temp_sensor = false; + break; + default: + *p_has_temp_sensor = temp ? true : false; + } + return 0; +} + +static int mlxsw_env_temp_event_set(struct mlxsw_core *mlxsw_core, + u16 sensor_index, bool enable) +{ + char mtmp_pl[MLXSW_REG_MTMP_LEN] = {0}; + enum mlxsw_reg_mtmp_tee tee; + int err, threshold_hi; + + mlxsw_reg_mtmp_sensor_index_set(mtmp_pl, sensor_index); + err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mtmp), mtmp_pl); + if (err) + return err; + + if (enable) { + err = mlxsw_env_module_temp_thresholds_get(mlxsw_core, + sensor_index - + MLXSW_REG_MTMP_MODULE_INDEX_MIN, + SFP_TEMP_HIGH_WARN, + &threshold_hi); + /* In case it is not possible to query the module's threshold, + * use the default value. + */ + if (err) + threshold_hi = MLXSW_REG_MTMP_THRESH_HI; + else + /* mlxsw_env_module_temp_thresholds_get() multiplies + * Celsius degrees by 1000 whereas MTMP expects + * temperature in 0.125 Celsius degrees units. + * Convert threshold_hi to correct units. + */ + threshold_hi = threshold_hi / 1000 * 8; + + mlxsw_reg_mtmp_temperature_threshold_hi_set(mtmp_pl, threshold_hi); + mlxsw_reg_mtmp_temperature_threshold_lo_set(mtmp_pl, threshold_hi - + MLXSW_REG_MTMP_HYSTERESIS_TEMP); + } + tee = enable ? MLXSW_REG_MTMP_TEE_GENERATE_EVENT : MLXSW_REG_MTMP_TEE_NO_EVENT; + mlxsw_reg_mtmp_tee_set(mtmp_pl, tee); + return mlxsw_reg_write(mlxsw_core, MLXSW_REG(mtmp), mtmp_pl); +} + +static int mlxsw_env_module_temp_event_enable(struct mlxsw_core *mlxsw_core, + u8 module_count) +{ + int i, err, sensor_index; + bool has_temp_sensor; + + for (i = 0; i < module_count; i++) { + err = mlxsw_env_module_has_temp_sensor(mlxsw_core, i, + &has_temp_sensor); + if (err) + return err; + + if (!has_temp_sensor) + continue; + + sensor_index = i + MLXSW_REG_MTMP_MODULE_INDEX_MIN; + err = mlxsw_env_temp_event_set(mlxsw_core, sensor_index, true); + if (err) + return err; + } + + return 0; +} + static void mlxsw_env_mtwe_event_func(const struct mlxsw_reg_info *reg, char *mtwe_pl, void *priv) { @@ -424,8 +517,14 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env) if (err) goto err_temp_warn_event_register; + err = mlxsw_env_module_temp_event_enable(mlxsw_core, env->module_count); + if (err) + goto err_temp_event_enable; + return 0; +err_temp_event_enable: + mlxsw_env_temp_warn_event_unregister(env); err_temp_warn_event_register: kfree(env); return err; diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 827906c9fdeb..e8415589d4fb 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -8516,6 +8516,13 @@ MLXSW_ITEM32(reg, mtmp, max_temperature, 0x08, 0, 16); * 2 - Generate single event * Access: RW */ + +enum mlxsw_reg_mtmp_tee { + MLXSW_REG_MTMP_TEE_NO_EVENT, + MLXSW_REG_MTMP_TEE_GENERATE_EVENT, + MLXSW_REG_MTMP_TEE_GENERATE_SINGLE_EVENT, +}; + MLXSW_ITEM32(reg, mtmp, tee, 0x0C, 30, 2); #define MLXSW_REG_MTMP_THRESH_HI 0x348 /* 105 Celsius */ @@ -8526,6 +8533,7 @@ MLXSW_ITEM32(reg, mtmp, tee, 0x0C, 30, 2); */ MLXSW_ITEM32(reg, mtmp, temperature_threshold_hi, 0x0C, 0, 16); +#define MLXSW_REG_MTMP_HYSTERESIS_TEMP 0x28 /* 5 Celsius */ /* reg_mtmp_temperature_threshold_lo * Low threshold for Temperature Warning Event. In 0.125 Celsius. * Access: RW |