drivers/net/ethernet/mellanox/mlxsw/spectrum_flow.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/mellanox/mlxsw/spectrum_flow.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlxsw/spectrum_flow.c
Extension
.c
Size
7593 bytes
Lines
296
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

if (IS_ERR(block_cb)) {
			mlxsw_sp_flow_block_destroy(flow_block);
			return PTR_ERR(block_cb);
		}
		register_block = true;
	} else {
		flow_block = flow_block_cb_priv(block_cb);
	}
	flow_block_cb_incref(block_cb);
	err = mlxsw_sp_flow_block_bind(mlxsw_sp, flow_block,
				       mlxsw_sp_port, ingress, f->extack);
	if (err)
		goto err_block_bind;

	if (ingress)
		mlxsw_sp_port->ing_flow_block = flow_block;
	else
		mlxsw_sp_port->eg_flow_block = flow_block;

	if (register_block) {
		flow_block_cb_add(block_cb, f);
		list_add_tail(&block_cb->driver_list, &mlxsw_sp_block_cb_list);
	}

	return 0;

err_block_bind:
	if (!flow_block_cb_decref(block_cb))
		flow_block_cb_free(block_cb);
	return err;
}

static void mlxsw_sp_setup_tc_block_unbind(struct mlxsw_sp_port *mlxsw_sp_port,
					   struct flow_block_offload *f,
					   bool ingress)
{
	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
	struct mlxsw_sp_flow_block *flow_block;
	struct flow_block_cb *block_cb;
	int err;

	block_cb = flow_block_cb_lookup(f->block, mlxsw_sp_flow_block_cb,
					mlxsw_sp);
	if (!block_cb)
		return;

	if (ingress)
		mlxsw_sp_port->ing_flow_block = NULL;
	else
		mlxsw_sp_port->eg_flow_block = NULL;

	flow_block = flow_block_cb_priv(block_cb);
	err = mlxsw_sp_flow_block_unbind(mlxsw_sp, flow_block,
					 mlxsw_sp_port, ingress);
	if (!err && !flow_block_cb_decref(block_cb)) {
		flow_block_cb_remove(block_cb, f);
		list_del(&block_cb->driver_list);
	}
}

int mlxsw_sp_setup_tc_block_clsact(struct mlxsw_sp_port *mlxsw_sp_port,
				   struct flow_block_offload *f,
				   bool ingress)
{
	f->driver_block_list = &mlxsw_sp_block_cb_list;

	switch (f->command) {
	case FLOW_BLOCK_BIND:
		return mlxsw_sp_setup_tc_block_bind(mlxsw_sp_port, f, ingress);
	case FLOW_BLOCK_UNBIND:
		mlxsw_sp_setup_tc_block_unbind(mlxsw_sp_port, f, ingress);
		return 0;
	default:
		return -EOPNOTSUPP;
	}
}

Annotation

Implementation Notes