Commit 05cf5828 authored by Amit Cohen's avatar Amit Cohen Committed by David S. Miller
Browse files

mlxsw: Update module's settings when module is plugged in



Module temperature warning events are enabled for modules that have a
temperature sensor and configured according to the temperature
thresholds queried from the module.

When a module is unplugged we are guaranteed not to get temperature
warning events. However, when a module is plugged in we need to
potentially update its current settings (i.e., event enablement and
thresholds).

Register to port module plug/unplug events and update module's settings
upon plug in events.

Signed-off-by: default avatarAmit Cohen <amcohen@nvidia.com>
Signed-off-by: default avatarIdo Schimmel <idosch@nvidia.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3bdbab3f
Loading
Loading
Loading
Loading
+126 −0
Original line number Diff line number Diff line
@@ -467,6 +467,117 @@ static void mlxsw_env_temp_warn_event_unregister(struct mlxsw_env *mlxsw_env)
				   &mlxsw_env_temp_warn_listener, mlxsw_env);
}

struct mlxsw_env_module_plug_unplug_event {
	struct mlxsw_env *mlxsw_env;
	u8 module;
	struct work_struct work;
};

static void mlxsw_env_pmpe_event_work(struct work_struct *work)
{
	struct mlxsw_env_module_plug_unplug_event *event;
	struct mlxsw_env *mlxsw_env;
	bool has_temp_sensor;
	u16 sensor_index;
	int err;

	event = container_of(work, struct mlxsw_env_module_plug_unplug_event,
			     work);
	mlxsw_env = event->mlxsw_env;

	spin_lock_bh(&mlxsw_env->module_info_lock);
	mlxsw_env->module_info[event->module].is_overheat = false;
	spin_unlock_bh(&mlxsw_env->module_info_lock);

	err = mlxsw_env_module_has_temp_sensor(mlxsw_env->core, event->module,
					       &has_temp_sensor);
	/* Do not disable events on modules without sensors or faulty sensors
	 * because FW returns errors.
	 */
	if (err)
		goto out;

	if (!has_temp_sensor)
		goto out;

	sensor_index = event->module + MLXSW_REG_MTMP_MODULE_INDEX_MIN;
	mlxsw_env_temp_event_set(mlxsw_env->core, sensor_index, true);

out:
	kfree(event);
}

static void
mlxsw_env_pmpe_listener_func(const struct mlxsw_reg_info *reg, char *pmpe_pl,
			     void *priv)
{
	struct mlxsw_env_module_plug_unplug_event *event;
	enum mlxsw_reg_pmpe_module_status module_status;
	u8 module = mlxsw_reg_pmpe_module_get(pmpe_pl);
	struct mlxsw_env *mlxsw_env = priv;

	if (WARN_ON_ONCE(module >= mlxsw_env->module_count))
		return;

	module_status = mlxsw_reg_pmpe_module_status_get(pmpe_pl);
	if (module_status != MLXSW_REG_PMPE_MODULE_STATUS_PLUGGED_ENABLED)
		return;

	event = kmalloc(sizeof(*event), GFP_ATOMIC);
	if (!event)
		return;

	event->mlxsw_env = mlxsw_env;
	event->module = module;
	INIT_WORK(&event->work, mlxsw_env_pmpe_event_work);
	mlxsw_core_schedule_work(&event->work);
}

static const struct mlxsw_listener mlxsw_env_module_plug_listener =
	MLXSW_EVENTL(mlxsw_env_pmpe_listener_func, PMPE, PMPE);

static int
mlxsw_env_module_plug_event_register(struct mlxsw_core *mlxsw_core)
{
	struct mlxsw_env *mlxsw_env = mlxsw_core_env(mlxsw_core);

	if (!mlxsw_core_temp_warn_enabled(mlxsw_core))
		return 0;

	return mlxsw_core_trap_register(mlxsw_core,
					&mlxsw_env_module_plug_listener,
					mlxsw_env);
}

static void
mlxsw_env_module_plug_event_unregister(struct mlxsw_env *mlxsw_env)
{
	if (!mlxsw_core_temp_warn_enabled(mlxsw_env->core))
		return;

	mlxsw_core_trap_unregister(mlxsw_env->core,
				   &mlxsw_env_module_plug_listener,
				   mlxsw_env);
}

static int
mlxsw_env_module_oper_state_event_enable(struct mlxsw_core *mlxsw_core,
					 u8 module_count)
{
	int i, err;

	for (i = 0; i < module_count; i++) {
		char pmaos_pl[MLXSW_REG_PMAOS_LEN];

		mlxsw_reg_pmaos_pack(pmaos_pl, i,
				     MLXSW_REG_PMAOS_E_GENERATE_EVENT);
		err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(pmaos), pmaos_pl);
		if (err)
			return err;
	}
	return 0;
}

int
mlxsw_env_module_overheat_counter_get(struct mlxsw_core *mlxsw_core, u8 module,
				      u64 *p_counter)
@@ -517,6 +628,15 @@ 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_plug_event_register(mlxsw_core);
	if (err)
		goto err_module_plug_event_register;

	err = mlxsw_env_module_oper_state_event_enable(mlxsw_core,
						       env->module_count);
	if (err)
		goto err_oper_state_event_enable;

	err = mlxsw_env_module_temp_event_enable(mlxsw_core, env->module_count);
	if (err)
		goto err_temp_event_enable;
@@ -524,6 +644,9 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env)
	return 0;

err_temp_event_enable:
err_oper_state_event_enable:
	mlxsw_env_module_plug_event_unregister(env);
err_module_plug_event_register:
	mlxsw_env_temp_warn_event_unregister(env);
err_temp_warn_event_register:
	kfree(env);
@@ -532,6 +655,9 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core, struct mlxsw_env **p_env)

void mlxsw_env_fini(struct mlxsw_env *env)
{
	mlxsw_env_module_plug_event_unregister(env);
	/* Make sure there is no more event work scheduled. */
	mlxsw_core_flush_owq();
	mlxsw_env_temp_warn_event_unregister(env);
	kfree(env);
}
+1 −0
Original line number Diff line number Diff line
@@ -5683,6 +5683,7 @@ enum mlxsw_reg_htgt_trap_group {
	MLXSW_REG_HTGT_TRAP_GROUP_EMAD,
	MLXSW_REG_HTGT_TRAP_GROUP_MFDE,
	MLXSW_REG_HTGT_TRAP_GROUP_MTWE,
	MLXSW_REG_HTGT_TRAP_GROUP_PMPE,
	MLXSW_REG_HTGT_TRAP_GROUP_SP_STP,
	MLXSW_REG_HTGT_TRAP_GROUP_SP_LACP,
	MLXSW_REG_HTGT_TRAP_GROUP_SP_LLDP,
+8 −0
Original line number Diff line number Diff line
@@ -2473,6 +2473,14 @@ static int mlxsw_sp_basic_trap_groups_set(struct mlxsw_core *mlxsw_core)
			    MLXSW_REG_HTGT_INVALID_POLICER,
			    MLXSW_REG_HTGT_DEFAULT_PRIORITY,
			    MLXSW_REG_HTGT_DEFAULT_TC);
	err = mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl);
	if (err)
		return err;

	mlxsw_reg_htgt_pack(htgt_pl, MLXSW_REG_HTGT_TRAP_GROUP_PMPE,
			    MLXSW_REG_HTGT_INVALID_POLICER,
			    MLXSW_REG_HTGT_DEFAULT_PRIORITY,
			    MLXSW_REG_HTGT_DEFAULT_TC);
	return mlxsw_reg_write(mlxsw_core, MLXSW_REG(htgt), htgt_pl);
}

+2 −0
Original line number Diff line number Diff line
@@ -124,6 +124,8 @@ enum mlxsw_event_trap_id {
	MLXSW_TRAP_ID_MFDE = 0x3,
	/* Port Up/Down event generated by hardware */
	MLXSW_TRAP_ID_PUDE = 0x8,
	/* Port Module Plug/Unplug Event generated by hardware */
	MLXSW_TRAP_ID_PMPE = 0x9,
	/* Temperature Warning event generated by hardware */
	MLXSW_TRAP_ID_MTWE = 0xC,
	/* PTP Ingress FIFO has a new entry */