mlxsw: Enable temperature event for all supported port module sensors
authorAmit Cohen <amcohen@nvidia.com>
Sun, 27 Sep 2020 07:50:12 +0000 (10:50 +0300)
committerDavid S. Miller <davem@davemloft.net>
Sun, 27 Sep 2020 20:27:01 +0000 (13:27 -0700)
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>
drivers/net/ethernet/mellanox/mlxsw/core_env.c
drivers/net/ethernet/mellanox/mlxsw/reg.h

index 06c0417..63dd1fb 100644 (file)
@@ -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;
index 827906c..e841558 100644 (file)
@@ -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