Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fba53f7b authored by Maor Gottlieb's avatar Maor Gottlieb Committed by David S. Miller
Browse files

net/mlx5: Introduce mlx5_flow_steering structure



Instead of having all steering private name spaces and
steering module fields flat in mlx5_core_priv, we wrap
them in mlx5_flow_steering for better modularity and
API exposure.

Signed-off-by: default avatarMaor Gottlieb <maorg@mellanox.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c5bb1730
Loading
Loading
Loading
Loading
+75 −59
Original line number Diff line number Diff line
@@ -1363,12 +1363,13 @@ void mlx5_destroy_flow_group(struct mlx5_flow_group *fg)
struct mlx5_flow_namespace *mlx5_get_flow_namespace(struct mlx5_core_dev *dev,
						    enum mlx5_flow_namespace_type type)
{
	struct mlx5_flow_root_namespace *root_ns = dev->priv.root_ns;
	struct mlx5_flow_steering *steering = dev->priv.steering;
	struct mlx5_flow_root_namespace *root_ns;
	int prio;
	struct fs_prio *fs_prio;
	struct mlx5_flow_namespace *ns;

	if (!root_ns)
	if (!steering)
		return NULL;

	switch (type) {
@@ -1380,24 +1381,28 @@ struct mlx5_flow_namespace *mlx5_get_flow_namespace(struct mlx5_core_dev *dev,
		prio = type;
		break;
	case MLX5_FLOW_NAMESPACE_FDB:
		if (dev->priv.fdb_root_ns)
			return &dev->priv.fdb_root_ns->ns;
		if (steering->fdb_root_ns)
			return &steering->fdb_root_ns->ns;
		else
			return NULL;
	case MLX5_FLOW_NAMESPACE_ESW_EGRESS:
		if (dev->priv.esw_egress_root_ns)
			return &dev->priv.esw_egress_root_ns->ns;
		if (steering->esw_egress_root_ns)
			return &steering->esw_egress_root_ns->ns;
		else
			return NULL;
	case MLX5_FLOW_NAMESPACE_ESW_INGRESS:
		if (dev->priv.esw_ingress_root_ns)
			return &dev->priv.esw_ingress_root_ns->ns;
		if (steering->esw_ingress_root_ns)
			return &steering->esw_ingress_root_ns->ns;
		else
			return NULL;
	default:
		return NULL;
	}

	root_ns = steering->root_ns;
	if (!root_ns)
		return NULL;

	fs_prio = find_prio(&root_ns->ns, prio);
	if (!fs_prio)
		return NULL;
@@ -1483,13 +1488,13 @@ static bool has_required_caps(struct mlx5_core_dev *dev, struct node_caps *caps)
	return true;
}

static int init_root_tree_recursive(struct mlx5_core_dev *dev,
static int init_root_tree_recursive(struct mlx5_flow_steering *steering,
				    struct init_tree_node *init_node,
				    struct fs_node *fs_parent_node,
				    struct init_tree_node *init_parent_node,
				    int prio)
{
	int max_ft_level = MLX5_CAP_FLOWTABLE(dev,
	int max_ft_level = MLX5_CAP_FLOWTABLE(steering->dev,
					      flow_table_properties_nic_receive.
					      max_ft_level);
	struct mlx5_flow_namespace *fs_ns;
@@ -1500,7 +1505,7 @@ static int init_root_tree_recursive(struct mlx5_core_dev *dev,

	if (init_node->type == FS_TYPE_PRIO) {
		if ((init_node->min_ft_level > max_ft_level) ||
		    !has_required_caps(dev, &init_node->caps))
		    !has_required_caps(steering->dev, &init_node->caps))
			return 0;

		fs_get_obj(fs_ns, fs_parent_node);
@@ -1521,7 +1526,7 @@ static int init_root_tree_recursive(struct mlx5_core_dev *dev,
	}
	prio = 0;
	for (i = 0; i < init_node->ar_size; i++) {
		err = init_root_tree_recursive(dev, &init_node->children[i],
		err = init_root_tree_recursive(steering, &init_node->children[i],
					       base, init_node, prio);
		if (err)
			return err;
@@ -1534,7 +1539,7 @@ static int init_root_tree_recursive(struct mlx5_core_dev *dev,
	return 0;
}

static int init_root_tree(struct mlx5_core_dev *dev,
static int init_root_tree(struct mlx5_flow_steering *steering,
			  struct init_tree_node *init_node,
			  struct fs_node *fs_parent_node)
{
@@ -1544,7 +1549,7 @@ static int init_root_tree(struct mlx5_core_dev *dev,

	fs_get_obj(fs_ns, fs_parent_node);
	for (i = 0; i < init_node->ar_size; i++) {
		err = init_root_tree_recursive(dev, &init_node->children[i],
		err = init_root_tree_recursive(steering, &init_node->children[i],
					       &fs_ns->node,
					       init_node, i);
		if (err)
@@ -1553,7 +1558,7 @@ static int init_root_tree(struct mlx5_core_dev *dev,
	return 0;
}

static struct mlx5_flow_root_namespace *create_root_ns(struct mlx5_core_dev *dev,
static struct mlx5_flow_root_namespace *create_root_ns(struct mlx5_flow_steering *steering,
						       enum fs_flow_table_type
						       table_type)
{
@@ -1565,7 +1570,7 @@ static struct mlx5_flow_root_namespace *create_root_ns(struct mlx5_core_dev *dev
	if (!root_ns)
		return NULL;

	root_ns->dev = dev;
	root_ns->dev = steering->dev;
	root_ns->table_type = table_type;

	ns = &root_ns->ns;
@@ -1620,46 +1625,45 @@ static void set_prio_attrs(struct mlx5_flow_root_namespace *root_ns)
#define ANCHOR_PRIO 0
#define ANCHOR_SIZE 1
#define ANCHOR_LEVEL 0
static int create_anchor_flow_table(struct mlx5_core_dev
							*dev)
static int create_anchor_flow_table(struct mlx5_flow_steering *steering)
{
	struct mlx5_flow_namespace *ns = NULL;
	struct mlx5_flow_table *ft;

	ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_ANCHOR);
	ns = mlx5_get_flow_namespace(steering->dev, MLX5_FLOW_NAMESPACE_ANCHOR);
	if (!ns)
		return -EINVAL;
	ft = mlx5_create_flow_table(ns, ANCHOR_PRIO, ANCHOR_SIZE, ANCHOR_LEVEL);
	if (IS_ERR(ft)) {
		mlx5_core_err(dev, "Failed to create last anchor flow table");
		mlx5_core_err(steering->dev, "Failed to create last anchor flow table");
		return PTR_ERR(ft);
	}
	return 0;
}

static int init_root_ns(struct mlx5_core_dev *dev)
static int init_root_ns(struct mlx5_flow_steering *steering)
{

	dev->priv.root_ns = create_root_ns(dev, FS_FT_NIC_RX);
	if (IS_ERR_OR_NULL(dev->priv.root_ns))
	steering->root_ns = create_root_ns(steering, FS_FT_NIC_RX);
	if (IS_ERR_OR_NULL(steering->root_ns))
		goto cleanup;

	if (init_root_tree(dev, &root_fs, &dev->priv.root_ns->ns.node))
	if (init_root_tree(steering, &root_fs, &steering->root_ns->ns.node))
		goto cleanup;

	set_prio_attrs(dev->priv.root_ns);
	set_prio_attrs(steering->root_ns);

	if (create_anchor_flow_table(dev))
	if (create_anchor_flow_table(steering))
		goto cleanup;

	return 0;

cleanup:
	mlx5_cleanup_fs(dev);
	mlx5_cleanup_fs(steering->dev);
	return -ENOMEM;
}

static void cleanup_single_prio_root_ns(struct mlx5_core_dev *dev,
static void cleanup_single_prio_root_ns(struct mlx5_flow_steering *steering,
					struct mlx5_flow_root_namespace *root_ns)
{
	struct fs_node *prio;
@@ -1672,11 +1676,11 @@ static void cleanup_single_prio_root_ns(struct mlx5_core_dev *dev,
					struct fs_node,
				 list);
		if (tree_remove_node(prio))
			mlx5_core_warn(dev,
			mlx5_core_warn(steering->dev,
				       "Flow steering priority wasn't destroyed, refcount > 1\n");
	}
	if (tree_remove_node(&root_ns->ns.node))
		mlx5_core_warn(dev,
		mlx5_core_warn(steering->dev,
			       "Flow steering namespace wasn't destroyed, refcount > 1\n");
	root_ns = NULL;
}
@@ -1690,12 +1694,12 @@ static void destroy_flow_tables(struct fs_prio *prio)
		mlx5_destroy_flow_table(iter);
}

static void cleanup_root_ns(struct mlx5_core_dev *dev)
static void cleanup_root_ns(struct mlx5_flow_steering *steering)
{
	struct mlx5_flow_root_namespace *root_ns = dev->priv.root_ns;
	struct mlx5_flow_root_namespace *root_ns = steering->root_ns;
	struct fs_prio *iter_prio;

	if (!MLX5_CAP_GEN(dev, nic_flow_table))
	if (!MLX5_CAP_GEN(steering->dev, nic_flow_table))
		return;

	if (!root_ns)
@@ -1720,7 +1724,7 @@ static void cleanup_root_ns(struct mlx5_core_dev *dev)
				fs_get_obj(obj_iter_prio2, iter_prio2);
				destroy_flow_tables(obj_iter_prio2);
				if (tree_remove_node(iter_prio2)) {
					mlx5_core_warn(dev,
					mlx5_core_warn(steering->dev,
						       "Priority %d wasn't destroyed, refcount > 1\n",
						       obj_iter_prio2->prio);
					return;
@@ -1737,7 +1741,7 @@ static void cleanup_root_ns(struct mlx5_core_dev *dev)
						 struct fs_node,
						 list);
			if (tree_remove_node(iter_ns)) {
				mlx5_core_warn(dev,
				mlx5_core_warn(steering->dev,
					       "Namespace wasn't destroyed, refcount > 1\n");
				return;
			}
@@ -1754,7 +1758,7 @@ static void cleanup_root_ns(struct mlx5_core_dev *dev)

		fs_get_obj(obj_prio_node, prio_node);
		if (tree_remove_node(prio_node)) {
			mlx5_core_warn(dev,
			mlx5_core_warn(steering->dev,
				       "Priority %d wasn't destroyed, refcount > 1\n",
				       obj_prio_node->prio);
			return;
@@ -1762,70 +1766,75 @@ static void cleanup_root_ns(struct mlx5_core_dev *dev)
	}

	if (tree_remove_node(&root_ns->ns.node)) {
		mlx5_core_warn(dev,
		mlx5_core_warn(steering->dev,
			       "root namespace wasn't destroyed, refcount > 1\n");
		return;
	}

	dev->priv.root_ns = NULL;
	steering->root_ns = NULL;
}

void mlx5_cleanup_fs(struct mlx5_core_dev *dev)
{
	struct mlx5_flow_steering *steering = dev->priv.steering;

	if (MLX5_CAP_GEN(dev, port_type) != MLX5_CAP_PORT_TYPE_ETH)
		return;

	cleanup_root_ns(dev);
	cleanup_single_prio_root_ns(dev, dev->priv.fdb_root_ns);
	cleanup_single_prio_root_ns(dev, dev->priv.esw_egress_root_ns);
	cleanup_single_prio_root_ns(dev, dev->priv.esw_ingress_root_ns);
	cleanup_root_ns(steering);
	cleanup_single_prio_root_ns(steering, steering->esw_egress_root_ns);
	cleanup_single_prio_root_ns(steering, steering->esw_ingress_root_ns);
	cleanup_single_prio_root_ns(steering, steering->fdb_root_ns);
	mlx5_cleanup_fc_stats(dev);
	kfree(steering);
}

static int init_fdb_root_ns(struct mlx5_core_dev *dev)
static int init_fdb_root_ns(struct mlx5_flow_steering *steering)
{
	struct fs_prio *prio;

	dev->priv.fdb_root_ns = create_root_ns(dev, FS_FT_FDB);
	if (!dev->priv.fdb_root_ns)
	steering->fdb_root_ns = create_root_ns(steering, FS_FT_FDB);
	if (!steering->fdb_root_ns)
		return -ENOMEM;

	/* Create single prio */
	prio = fs_create_prio(&dev->priv.fdb_root_ns->ns, 0, 1);
	prio = fs_create_prio(&steering->fdb_root_ns->ns, 0, 1);
	if (IS_ERR(prio)) {
		cleanup_single_prio_root_ns(dev, dev->priv.fdb_root_ns);
		cleanup_single_prio_root_ns(steering, steering->fdb_root_ns);
		return PTR_ERR(prio);
	} else {
		return 0;
	}
}

static int init_egress_acl_root_ns(struct mlx5_core_dev *dev)
static int init_ingress_acl_root_ns(struct mlx5_flow_steering *steering)
{
	struct fs_prio *prio;

	dev->priv.esw_egress_root_ns = create_root_ns(dev, FS_FT_ESW_EGRESS_ACL);
	if (!dev->priv.esw_egress_root_ns)
	steering->esw_egress_root_ns = create_root_ns(steering, FS_FT_ESW_EGRESS_ACL);
	if (!steering->esw_egress_root_ns)
		return -ENOMEM;

	/* create 1 prio*/
	prio = fs_create_prio(&dev->priv.esw_egress_root_ns->ns, 0, MLX5_TOTAL_VPORTS(dev));
	prio = fs_create_prio(&steering->esw_egress_root_ns->ns, 0,
			      MLX5_TOTAL_VPORTS(steering->dev));
	if (IS_ERR(prio))
		return PTR_ERR(prio);
	else
		return 0;
}

static int init_ingress_acl_root_ns(struct mlx5_core_dev *dev)
static int init_egress_acl_root_ns(struct mlx5_flow_steering *steering)
{
	struct fs_prio *prio;

	dev->priv.esw_ingress_root_ns = create_root_ns(dev, FS_FT_ESW_INGRESS_ACL);
	if (!dev->priv.esw_ingress_root_ns)
	steering->esw_ingress_root_ns = create_root_ns(steering, FS_FT_ESW_INGRESS_ACL);
	if (!steering->esw_ingress_root_ns)
		return -ENOMEM;

	/* create 1 prio*/
	prio = fs_create_prio(&dev->priv.esw_ingress_root_ns->ns, 0, MLX5_TOTAL_VPORTS(dev));
	prio = fs_create_prio(&steering->esw_ingress_root_ns->ns, 0,
			      MLX5_TOTAL_VPORTS(steering->dev));
	if (IS_ERR(prio))
		return PTR_ERR(prio);
	else
@@ -1834,6 +1843,7 @@ static int init_ingress_acl_root_ns(struct mlx5_core_dev *dev)

int mlx5_init_fs(struct mlx5_core_dev *dev)
{
	struct mlx5_flow_steering *steering;
	int err = 0;

	if (MLX5_CAP_GEN(dev, port_type) != MLX5_CAP_PORT_TYPE_ETH)
@@ -1843,26 +1853,32 @@ int mlx5_init_fs(struct mlx5_core_dev *dev)
	if (err)
		return err;

	steering = kzalloc(sizeof(*steering), GFP_KERNEL);
	if (!steering)
		return -ENOMEM;
	steering->dev = dev;
	dev->priv.steering = steering;

	if (MLX5_CAP_GEN(dev, nic_flow_table) &&
	    MLX5_CAP_FLOWTABLE_NIC_RX(dev, ft_support)) {
		err = init_root_ns(dev);
		err = init_root_ns(steering);
		if (err)
			goto err;
	}

	if (MLX5_CAP_GEN(dev, eswitch_flow_table)) {
		if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev, ft_support)) {
			err = init_fdb_root_ns(dev);
			err = init_fdb_root_ns(steering);
			if (err)
				goto err;
		}
		if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support)) {
			err = init_egress_acl_root_ns(dev);
			err = init_egress_acl_root_ns(steering);
			if (err)
				goto err;
		}
		if (MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support)) {
			err = init_ingress_acl_root_ns(dev);
			err = init_ingress_acl_root_ns(steering);
			if (err)
				goto err;
		}
+8 −0
Original line number Diff line number Diff line
@@ -55,6 +55,14 @@ enum fs_fte_status {
	FS_FTE_STATUS_EXISTING = 1UL << 0,
};

struct mlx5_flow_steering {
	struct mlx5_core_dev *dev;
	struct mlx5_flow_root_namespace *root_ns;
	struct mlx5_flow_root_namespace *fdb_root_ns;
	struct mlx5_flow_root_namespace *esw_egress_root_ns;
	struct mlx5_flow_root_namespace *esw_ingress_root_ns;
};

struct fs_node {
	struct list_head	list;
	struct list_head	children;
+1 −5
Original line number Diff line number Diff line
@@ -550,14 +550,10 @@ struct mlx5_priv {
	struct list_head        ctx_list;
	spinlock_t              ctx_lock;

	struct mlx5_flow_steering *steering;
	struct mlx5_eswitch     *eswitch;
	struct mlx5_core_sriov	sriov;
	unsigned long		pci_dev_data;
	struct mlx5_flow_root_namespace *root_ns;
	struct mlx5_flow_root_namespace *fdb_root_ns;
	struct mlx5_flow_root_namespace *esw_egress_root_ns;
	struct mlx5_flow_root_namespace *esw_ingress_root_ns;

	struct mlx5_fc_stats		fc_stats;
	struct mlx5_rl_table            rl_table;
};