Commit 163f3d2d authored by Ido Schimmel's avatar Ido Schimmel Committed by David S. Miller
Browse files

mlxsw: core_env: Defer handling of module temperature warning events



Module temperature events are currently handled in softIRQ context,
requiring the 'module_info_lock' to be a spin lock. In future patchsets
we will need to be able to hold the lock while sleeping.

Therefore, defer handling of these events using a work queue so that the
next patch will be able to convert the lock to a mutex.

Signed-off-by: default avatarIdo Schimmel <idosch@nvidia.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 25a91f83
Loading
Loading
Loading
Loading
+34 −5
Original line number Diff line number Diff line
@@ -482,20 +482,30 @@ static int mlxsw_env_module_temp_event_enable(struct mlxsw_core *mlxsw_core,
	return 0;
}

static void mlxsw_env_mtwe_event_func(const struct mlxsw_reg_info *reg,
				      char *mtwe_pl, void *priv)
struct mlxsw_env_module_temp_warn_event {
	struct mlxsw_env *mlxsw_env;
	char mtwe_pl[MLXSW_REG_MTWE_LEN];
	struct work_struct work;
};

static void mlxsw_env_mtwe_event_work(struct work_struct *work)
{
	struct mlxsw_env *mlxsw_env = priv;
	struct mlxsw_env_module_temp_warn_event *event;
	struct mlxsw_env *mlxsw_env;
	int i, sensor_warning;
	bool is_overheat;

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

	for (i = 0; i < mlxsw_env->module_count; i++) {
		/* 64-127 of sensor_index are mapped to the port modules
		 * sequentially (module 0 is mapped to sensor_index 64,
		 * module 1 to sensor_index 65 and so on)
		 */
		sensor_warning =
			mlxsw_reg_mtwe_sensor_warning_get(mtwe_pl,
			mlxsw_reg_mtwe_sensor_warning_get(event->mtwe_pl,
							  i + MLXSW_REG_MTMP_MODULE_INDEX_MIN);
		spin_lock(&mlxsw_env->module_info_lock);
		is_overheat =
@@ -524,10 +534,29 @@ static void mlxsw_env_mtwe_event_func(const struct mlxsw_reg_info *reg,
			spin_unlock(&mlxsw_env->module_info_lock);
		}
	}

	kfree(event);
}

static void
mlxsw_env_mtwe_listener_func(const struct mlxsw_reg_info *reg, char *mtwe_pl,
			     void *priv)
{
	struct mlxsw_env_module_temp_warn_event *event;
	struct mlxsw_env *mlxsw_env = priv;

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

	event->mlxsw_env = mlxsw_env;
	memcpy(event->mtwe_pl, mtwe_pl, MLXSW_REG_MTWE_LEN);
	INIT_WORK(&event->work, mlxsw_env_mtwe_event_work);
	mlxsw_core_schedule_work(&event->work);
}

static const struct mlxsw_listener mlxsw_env_temp_warn_listener =
	MLXSW_EVENTL(mlxsw_env_mtwe_event_func, MTWE, MTWE);
	MLXSW_EVENTL(mlxsw_env_mtwe_listener_func, MTWE, MTWE);

static int mlxsw_env_temp_warn_event_register(struct mlxsw_core *mlxsw_core)
{