hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
....@@ -802,7 +802,7 @@
802802 struct fs_node *iter = list_entry(start, struct fs_node, list);
803803 struct mlx5_flow_table *ft = NULL;
804804
805
- if (!root || root->type == FS_TYPE_PRIO_CHAINS)
805
+ if (!root)
806806 return NULL;
807807
808808 list_for_each_advance_continue(iter, &root->children, reverse) {
....@@ -818,20 +818,42 @@
818818 return ft;
819819 }
820820
821
-/* If reverse is false then return the first flow table in next priority of
822
- * prio in the tree, else return the last flow table in the previous priority
823
- * of prio in the tree.
824
- */
825
-static struct mlx5_flow_table *find_closest_ft(struct fs_prio *prio, bool reverse)
821
+static struct fs_node *find_prio_chains_parent(struct fs_node *parent,
822
+ struct fs_node **child)
826823 {
824
+ struct fs_node *node = NULL;
825
+
826
+ while (parent && parent->type != FS_TYPE_PRIO_CHAINS) {
827
+ node = parent;
828
+ parent = parent->parent;
829
+ }
830
+
831
+ if (child)
832
+ *child = node;
833
+
834
+ return parent;
835
+}
836
+
837
+/* If reverse is false then return the first flow table next to the passed node
838
+ * in the tree, else return the last flow table before the node in the tree.
839
+ * If skip is true, skip the flow tables in the same prio_chains prio.
840
+ */
841
+static struct mlx5_flow_table *find_closest_ft(struct fs_node *node, bool reverse,
842
+ bool skip)
843
+{
844
+ struct fs_node *prio_chains_parent = NULL;
827845 struct mlx5_flow_table *ft = NULL;
828846 struct fs_node *curr_node;
829847 struct fs_node *parent;
830848
831
- parent = prio->node.parent;
832
- curr_node = &prio->node;
849
+ if (skip)
850
+ prio_chains_parent = find_prio_chains_parent(node, NULL);
851
+ parent = node->parent;
852
+ curr_node = node;
833853 while (!ft && parent) {
834
- ft = find_closest_ft_recursive(parent, &curr_node->list, reverse);
854
+ if (parent != prio_chains_parent)
855
+ ft = find_closest_ft_recursive(parent, &curr_node->list,
856
+ reverse);
835857 curr_node = parent;
836858 parent = curr_node->parent;
837859 }
....@@ -839,15 +861,15 @@
839861 }
840862
841863 /* Assuming all the tree is locked by mutex chain lock */
842
-static struct mlx5_flow_table *find_next_chained_ft(struct fs_prio *prio)
864
+static struct mlx5_flow_table *find_next_chained_ft(struct fs_node *node)
843865 {
844
- return find_closest_ft(prio, false);
866
+ return find_closest_ft(node, false, true);
845867 }
846868
847869 /* Assuming all the tree is locked by mutex chain lock */
848
-static struct mlx5_flow_table *find_prev_chained_ft(struct fs_prio *prio)
870
+static struct mlx5_flow_table *find_prev_chained_ft(struct fs_node *node)
849871 {
850
- return find_closest_ft(prio, true);
872
+ return find_closest_ft(node, true, true);
851873 }
852874
853875 static struct mlx5_flow_table *find_next_fwd_ft(struct mlx5_flow_table *ft,
....@@ -859,7 +881,7 @@
859881 next_ns = flow_act->action & MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_NS;
860882 fs_get_obj(prio, next_ns ? ft->ns->node.parent : ft->node.parent);
861883
862
- return find_next_chained_ft(prio);
884
+ return find_next_chained_ft(&prio->node);
863885 }
864886
865887 static int connect_fts_in_prio(struct mlx5_core_dev *dev,
....@@ -883,21 +905,55 @@
883905 return 0;
884906 }
885907
908
+static struct mlx5_flow_table *find_closet_ft_prio_chains(struct fs_node *node,
909
+ struct fs_node *parent,
910
+ struct fs_node **child,
911
+ bool reverse)
912
+{
913
+ struct mlx5_flow_table *ft;
914
+
915
+ ft = find_closest_ft(node, reverse, false);
916
+
917
+ if (ft && parent == find_prio_chains_parent(&ft->node, child))
918
+ return ft;
919
+
920
+ return NULL;
921
+}
922
+
886923 /* Connect flow tables from previous priority of prio to ft */
887924 static int connect_prev_fts(struct mlx5_core_dev *dev,
888925 struct mlx5_flow_table *ft,
889926 struct fs_prio *prio)
890927 {
928
+ struct fs_node *prio_parent, *parent = NULL, *child, *node;
891929 struct mlx5_flow_table *prev_ft;
930
+ int err = 0;
892931
893
- prev_ft = find_prev_chained_ft(prio);
894
- if (prev_ft) {
932
+ prio_parent = find_prio_chains_parent(&prio->node, &child);
933
+
934
+ /* return directly if not under the first sub ns of prio_chains prio */
935
+ if (prio_parent && !list_is_first(&child->list, &prio_parent->children))
936
+ return 0;
937
+
938
+ prev_ft = find_prev_chained_ft(&prio->node);
939
+ while (prev_ft) {
895940 struct fs_prio *prev_prio;
896941
897942 fs_get_obj(prev_prio, prev_ft->node.parent);
898
- return connect_fts_in_prio(dev, prev_prio, ft);
943
+ err = connect_fts_in_prio(dev, prev_prio, ft);
944
+ if (err)
945
+ break;
946
+
947
+ if (!parent) {
948
+ parent = find_prio_chains_parent(&prev_prio->node, &child);
949
+ if (!parent)
950
+ break;
951
+ }
952
+
953
+ node = child;
954
+ prev_ft = find_closet_ft_prio_chains(node, parent, &child, true);
899955 }
900
- return 0;
956
+ return err;
901957 }
902958
903959 static int update_root_ft_create(struct mlx5_flow_table *ft, struct fs_prio
....@@ -1036,7 +1092,7 @@
10361092 if (err)
10371093 return err;
10381094
1039
- next_ft = first_ft ? first_ft : find_next_chained_ft(prio);
1095
+ next_ft = first_ft ? first_ft : find_next_chained_ft(&prio->node);
10401096 err = connect_fwd_rules(dev, ft, next_ft);
10411097 if (err)
10421098 return err;
....@@ -1114,7 +1170,7 @@
11141170 tree_init_node(&ft->node, del_hw_flow_table, del_sw_flow_table);
11151171 log_table_sz = ft->max_fte ? ilog2(ft->max_fte) : 0;
11161172 next_ft = unmanaged ? ft_attr->next_ft :
1117
- find_next_chained_ft(fs_prio);
1173
+ find_next_chained_ft(&fs_prio->node);
11181174 ft->def_miss_action = ns->def_miss_action;
11191175 ft->ns = ns;
11201176 err = root->cmds->create_flow_table(root, ft, log_table_sz, next_ft);
....@@ -2073,13 +2129,20 @@
20732129 /* Assuming prio->node.children(flow tables) is sorted by level */
20742130 static struct mlx5_flow_table *find_next_ft(struct mlx5_flow_table *ft)
20752131 {
2132
+ struct fs_node *prio_parent, *child;
20762133 struct fs_prio *prio;
20772134
20782135 fs_get_obj(prio, ft->node.parent);
20792136
20802137 if (!list_is_last(&ft->node.list, &prio->node.children))
20812138 return list_next_entry(ft, node.list);
2082
- return find_next_chained_ft(prio);
2139
+
2140
+ prio_parent = find_prio_chains_parent(&prio->node, &child);
2141
+
2142
+ if (prio_parent && list_is_first(&child->list, &prio_parent->children))
2143
+ return find_closest_ft(&prio->node, false, false);
2144
+
2145
+ return find_next_chained_ft(&prio->node);
20832146 }
20842147
20852148 static int update_root_ft_destroy(struct mlx5_flow_table *ft)