drivers/net/ethernet/mellanox/mlx5/core/esw/vporttbl.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlx5/core/esw/vporttbl.c
Extension
.c
Size
3765 bytes
Lines
151
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_vport_key {
	u32 chain;
	u16 prio;
	u16 vport;
	u16 vhca_id;
	struct esw_vport_tbl_namespace *vport_ns;
} __packed;

struct mlx5_vport_table {
	struct hlist_node hlist;
	struct mlx5_flow_table *fdb;
	u32 num_rules;
	struct mlx5_vport_key key;
};

static void
esw_vport_tbl_init(struct mlx5_eswitch *esw, struct esw_vport_tbl_namespace *ns)
{
	if (esw->offloads.encap != DEVLINK_ESWITCH_ENCAP_MODE_NONE)
		ns->flags |= (MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT |
			      MLX5_FLOW_TABLE_TUNNEL_EN_DECAP);
}

static struct mlx5_flow_table *
esw_vport_tbl_create(struct mlx5_eswitch *esw, struct mlx5_flow_namespace *ns,
		     const struct esw_vport_tbl_namespace *vport_ns)
{
	struct mlx5_flow_table_attr ft_attr = {};
	struct mlx5_flow_table *fdb;

	if (vport_ns->max_num_groups)
		ft_attr.autogroup.max_num_groups = vport_ns->max_num_groups;
	else
		ft_attr.autogroup.max_num_groups = esw->params.large_group_num;
	ft_attr.max_fte = vport_ns->max_fte;
	ft_attr.prio = FDB_PER_VPORT;
	ft_attr.flags = vport_ns->flags;
	fdb = mlx5_create_auto_grouped_flow_table(ns, &ft_attr);
	if (IS_ERR(fdb)) {
		esw_warn(esw->dev, "Failed to create per vport FDB Table err %pe\n",
			 fdb);
	}

	return fdb;
}

static u32 flow_attr_to_vport_key(struct mlx5_eswitch *esw,
				  struct mlx5_vport_tbl_attr *attr,
				  struct mlx5_vport_key *key)
{
	key->vport = attr->vport;
	key->chain = attr->chain;
	key->prio = attr->prio;
	key->vhca_id = MLX5_CAP_GEN(esw->dev, vhca_id);
	key->vport_ns  = attr->vport_ns;
	return jhash(key, sizeof(*key), 0);
}

/* caller must hold vports.lock */
static struct mlx5_vport_table *
esw_vport_tbl_lookup(struct mlx5_eswitch *esw, struct mlx5_vport_key *skey, u32 key)
{
	struct mlx5_vport_table *e;

	hash_for_each_possible(esw->fdb_table.offloads.vports.table, e, hlist, key)
		if (!memcmp(&e->key, skey, sizeof(*skey)))
			return e;

	return NULL;
}

struct mlx5_flow_table *
mlx5_esw_vporttbl_get(struct mlx5_eswitch *esw, struct mlx5_vport_tbl_attr *attr)
{
	struct mlx5_core_dev *dev = esw->dev;
	struct mlx5_flow_namespace *ns;
	struct mlx5_flow_table *fdb;
	struct mlx5_vport_table *e;
	struct mlx5_vport_key skey;
	u32 hkey;

	mutex_lock(&esw->fdb_table.offloads.vports.lock);
	esw_vport_tbl_init(esw, attr->vport_ns);
	hkey = flow_attr_to_vport_key(esw, attr, &skey);
	e = esw_vport_tbl_lookup(esw, &skey, hkey);
	if (e) {
		e->num_rules++;
		goto out;
	}

Annotation

Implementation Notes