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

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c
Extension
.c
Size
15263 bytes
Lines
564
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_sf {
	struct mlx5_devlink_port dl_port;
	unsigned int port_index;
	u32 controller;
	u16 id;
	u16 hw_fn_id;
	u16 hw_state;
};

static void *mlx5_sf_by_dl_port(struct devlink_port *dl_port)
{
	struct mlx5_devlink_port *mlx5_dl_port = mlx5_devlink_port_get(dl_port);

	return container_of(mlx5_dl_port, struct mlx5_sf, dl_port);
}

struct mlx5_sf_table {
	struct mlx5_core_dev *dev; /* To refer from notifier context. */
	struct xarray function_ids; /* function id based lookup. */
	struct mutex sf_state_lock; /* Serializes sf state among user cmds & vhca event handler. */
};

static struct mlx5_sf *
mlx5_sf_lookup_by_function_id(struct mlx5_sf_table *table, unsigned int fn_id)
{
	return xa_load(&table->function_ids, fn_id);
}

static int mlx5_sf_function_id_insert(struct mlx5_sf_table *table, struct mlx5_sf *sf)
{
	return xa_insert(&table->function_ids, sf->hw_fn_id, sf, GFP_KERNEL);
}

static void mlx5_sf_function_id_erase(struct mlx5_sf_table *table, struct mlx5_sf *sf)
{
	xa_erase(&table->function_ids, sf->hw_fn_id);
}

static struct mlx5_sf *
mlx5_sf_alloc(struct mlx5_sf_table *table, struct mlx5_eswitch *esw,
	      u32 controller, u32 sfnum, struct netlink_ext_ack *extack)
{
	unsigned int dl_port_index;
	struct mlx5_sf *sf;
	u16 hw_fn_id;
	int id_err;
	int err;

	if (!mlx5_esw_offloads_controller_valid(esw, controller)) {
		NL_SET_ERR_MSG_MOD(extack, "Invalid controller number");
		return ERR_PTR(-EINVAL);
	}

	id_err = mlx5_sf_hw_table_sf_alloc(table->dev, controller, sfnum);
	if (id_err < 0) {
		err = id_err;
		goto id_err;
	}

	sf = kzalloc_obj(*sf);
	if (!sf) {
		err = -ENOMEM;
		goto alloc_err;
	}
	sf->id = id_err;
	hw_fn_id = mlx5_sf_sw_to_hw_id(table->dev, controller, sf->id);
	dl_port_index = mlx5_esw_vport_to_devlink_port_index(table->dev, hw_fn_id);
	sf->port_index = dl_port_index;
	sf->hw_fn_id = hw_fn_id;
	sf->hw_state = MLX5_VHCA_STATE_ALLOCATED;
	sf->controller = controller;

	err = mlx5_sf_function_id_insert(table, sf);
	if (err)
		goto insert_err;

	return sf;

insert_err:
	kfree(sf);
alloc_err:
	mlx5_sf_hw_table_sf_free(table->dev, controller, id_err);
id_err:
	if (err == -EEXIST)
		NL_SET_ERR_MSG_MOD(extack, "SF already exist. Choose different sfnum");
	return ERR_PTR(err);
}

static void mlx5_sf_free(struct mlx5_sf_table *table, struct mlx5_sf *sf)
{

Annotation

Implementation Notes