drivers/net/ethernet/mellanox/mlx5/core/sf/vhca_event.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/mellanox/mlx5/core/sf/vhca_event.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlx5/core/sf/vhca_event.c
Extension
.c
Size
6833 bytes
Lines
236
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct mlx5_vhca_event_work {
	struct work_struct work;
	struct mlx5_core_dev *dev;
	struct mlx5_vhca_state_event event;
};

struct mlx5_vhca_event_handler {
	struct workqueue_struct *wq;
};

struct mlx5_vhca_events {
	struct mlx5_core_dev *dev;
	struct mlx5_vhca_event_handler handler[MLX5_DEV_MAX_WQS];
};

int mlx5_cmd_query_vhca_state(struct mlx5_core_dev *dev, u16 function_id, u32 *out, u32 outlen)
{
	u32 in[MLX5_ST_SZ_DW(query_vhca_state_in)] = {};

	MLX5_SET(query_vhca_state_in, in, opcode, MLX5_CMD_OP_QUERY_VHCA_STATE);
	MLX5_SET(query_vhca_state_in, in, function_id, function_id);
	MLX5_SET(query_vhca_state_in, in, embedded_cpu_function, 0);

	return mlx5_cmd_exec(dev, in, sizeof(in), out, outlen);
}

static int mlx5_cmd_modify_vhca_state(struct mlx5_core_dev *dev, u16 function_id,
				      u32 *in, u32 inlen)
{
	u32 out[MLX5_ST_SZ_DW(modify_vhca_state_out)] = {};

	MLX5_SET(modify_vhca_state_in, in, opcode, MLX5_CMD_OP_MODIFY_VHCA_STATE);
	MLX5_SET(modify_vhca_state_in, in, function_id, function_id);
	MLX5_SET(modify_vhca_state_in, in, embedded_cpu_function, 0);

	return mlx5_cmd_exec(dev, in, inlen, out, sizeof(out));
}

int mlx5_modify_vhca_sw_id(struct mlx5_core_dev *dev, u16 function_id, u32 sw_fn_id)
{
	u32 out[MLX5_ST_SZ_DW(modify_vhca_state_out)] = {};
	u32 in[MLX5_ST_SZ_DW(modify_vhca_state_in)] = {};

	MLX5_SET(modify_vhca_state_in, in, opcode, MLX5_CMD_OP_MODIFY_VHCA_STATE);
	MLX5_SET(modify_vhca_state_in, in, function_id, function_id);
	MLX5_SET(modify_vhca_state_in, in, embedded_cpu_function, 0);
	MLX5_SET(modify_vhca_state_in, in, vhca_state_field_select.sw_function_id, 1);
	MLX5_SET(modify_vhca_state_in, in, vhca_state_context.sw_function_id, sw_fn_id);

	return mlx5_cmd_exec_inout(dev, modify_vhca_state, in, out);
}

int mlx5_vhca_event_arm(struct mlx5_core_dev *dev, u16 function_id)
{
	u32 in[MLX5_ST_SZ_DW(modify_vhca_state_in)] = {};

	MLX5_SET(modify_vhca_state_in, in, vhca_state_context.arm_change_event, 1);
	MLX5_SET(modify_vhca_state_in, in, vhca_state_field_select.arm_change_event, 1);

	return mlx5_cmd_modify_vhca_state(dev, function_id, in, sizeof(in));
}

static void
mlx5_vhca_event_notify(struct mlx5_core_dev *dev, struct mlx5_vhca_state_event *event)
{
	u32 out[MLX5_ST_SZ_DW(query_vhca_state_out)] = {};
	int err;

	err = mlx5_cmd_query_vhca_state(dev, event->function_id, out, sizeof(out));
	if (err)
		return;

	event->sw_function_id = MLX5_GET(query_vhca_state_out, out,
					 vhca_state_context.sw_function_id);
	event->new_vhca_state = MLX5_GET(query_vhca_state_out, out,
					 vhca_state_context.vhca_state);

	mlx5_vhca_event_arm(dev, event->function_id);
	trace_mlx5_sf_vhca_event(dev, event);

	blocking_notifier_call_chain(&dev->priv.vhca_state_n_head, 0, event);
}

static void mlx5_vhca_state_work_handler(struct work_struct *_work)
{
	struct mlx5_vhca_event_work *work = container_of(_work, struct mlx5_vhca_event_work, work);

	mlx5_vhca_event_notify(work->dev, &work->event);
	kfree(work);
}

Annotation

Implementation Notes