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

Commit 46719d77 authored by Maor Gottlieb's avatar Maor Gottlieb Committed by Saeed Mahameed
Browse files

net/mlx5: Export building of matched flow groups list



Refactor the code and export the build of the matched flow groups
list to separate function.

Signed-off-by: default avatarMaor Gottlieb <maorg@mellanox.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@mellanox.com>
parent 75d1d187
Loading
Loading
Loading
Loading
+64 −36
Original line number Diff line number Diff line
@@ -1441,47 +1441,87 @@ static bool dest_is_valid(struct mlx5_flow_destination *dest,
	return true;
}

static struct mlx5_flow_handle *
try_add_to_existing_fg(struct mlx5_flow_table *ft,
		       struct mlx5_flow_spec *spec,
		       struct mlx5_flow_act *flow_act,
		       struct mlx5_flow_destination *dest,
		       int dest_num)
{
	struct mlx5_flow_group *g;
	struct mlx5_flow_handle *rule;
	struct rhlist_head *tmp, *list;
struct match_list {
	struct list_head	list;
	struct mlx5_flow_group *g;
	} match_list, *iter;
	LIST_HEAD(match_head);
};

struct match_list_head {
	struct list_head  list;
	struct match_list first;
};

static void free_match_list(struct match_list_head *head)
{
	if (!list_empty(&head->list)) {
		struct match_list *iter, *match_tmp;

		list_del(&head->first.list);
		list_for_each_entry_safe(iter, match_tmp, &head->list,
					 list) {
			list_del(&iter->list);
			kfree(iter);
		}
	}
}

static int build_match_list(struct match_list_head *match_head,
			    struct mlx5_flow_table *ft,
			    struct mlx5_flow_spec *spec)
{
	struct rhlist_head *tmp, *list;
	struct mlx5_flow_group *g;
	int err = 0;

	rcu_read_lock();
	INIT_LIST_HEAD(&match_head->list);
	/* Collect all fgs which has a matching match_criteria */
	list = rhltable_lookup(&ft->fgs_hash, spec, rhash_fg);
	/* RCU is atomic, we can't execute FW commands here */
	rhl_for_each_entry_rcu(g, tmp, list, hash) {
		struct match_list *curr_match;

		if (likely(list_empty(&match_head))) {
			match_list.g = g;
			list_add_tail(&match_list.list, &match_head);
		if (likely(list_empty(&match_head->list))) {
			match_head->first.g = g;
			list_add_tail(&match_head->first.list,
				      &match_head->list);
			continue;
		}
		curr_match = kmalloc(sizeof(*curr_match), GFP_ATOMIC);

		curr_match = kmalloc(sizeof(*curr_match), GFP_ATOMIC);
		if (!curr_match) {
			rcu_read_unlock();
			rule = ERR_PTR(-ENOMEM);
			goto free_list;
			free_match_list(match_head);
			err = -ENOMEM;
			goto out;
		}
		curr_match->g = g;
		list_add_tail(&curr_match->list, &match_head);
		list_add_tail(&curr_match->list, &match_head->list);
	}
out:
	rcu_read_unlock();
	return err;
}

static struct mlx5_flow_handle *
try_add_to_existing_fg(struct mlx5_flow_table *ft,
		       struct mlx5_flow_spec *spec,
		       struct mlx5_flow_act *flow_act,
		       struct mlx5_flow_destination *dest,
		       int dest_num)
{
	struct mlx5_flow_group *g;
	struct mlx5_flow_handle *rule;
	struct match_list_head match_head;
	struct match_list *iter;
	int err;

	/* Collect all fgs which has a matching match_criteria */
	err = build_match_list(&match_head, ft, spec);
	if (err)
		return ERR_PTR(err);

	/* Try to find a fg that already contains a matching fte */
	list_for_each_entry(iter, &match_head, list) {
	list_for_each_entry(iter, &match_head.list, list) {
		struct fs_fte *fte;

		g = iter->g;
@@ -1500,7 +1540,7 @@ try_add_to_existing_fg(struct mlx5_flow_table *ft,
	/* No group with matching fte found. Try to add a new fte to any
	 * matching fg.
	 */
	list_for_each_entry(iter, &match_head, list) {
	list_for_each_entry(iter, &match_head.list, list) {
		g = iter->g;

		nested_lock_ref_node(&g->node, FS_MUTEX_PARENT);
@@ -1516,19 +1556,7 @@ try_add_to_existing_fg(struct mlx5_flow_table *ft,
	rule = ERR_PTR(-ENOENT);

free_list:
	if (!list_empty(&match_head)) {
		struct match_list *match_tmp;

		/* The most common case is having one FG. Since we want to
		 * optimize this case, we save the first on the stack.
		 * Therefore, no need to free it.
		 */
		list_del(&list_first_entry(&match_head, typeof(*iter), list)->list);
		list_for_each_entry_safe(iter, match_tmp, &match_head, list) {
			list_del(&iter->list);
			kfree(iter);
		}
	}
	free_match_list(&match_head);

	return rule;
}