@@ -510,6 +510,29 @@ static struct mlx5_flow_table *find_prev_chained_ft(struct fs_prio *prio)
510510 return find_closest_ft (prio , true);
511511}
512512
513+ static int update_root_ft_create (struct mlx5_flow_table * ft , struct fs_prio
514+ * prio )
515+ {
516+ struct mlx5_flow_root_namespace * root = find_root (& prio -> node );
517+ int min_level = INT_MAX ;
518+ int err ;
519+
520+ if (root -> root_ft )
521+ min_level = root -> root_ft -> level ;
522+
523+ if (ft -> level >= min_level )
524+ return 0 ;
525+
526+ err = mlx5_cmd_update_root_ft (root -> dev , ft );
527+ if (err )
528+ mlx5_core_warn (root -> dev , "Update root flow table of id=%u failed\n" ,
529+ ft -> id );
530+ else
531+ root -> root_ft = ft ;
532+
533+ return err ;
534+ }
535+
513536struct mlx5_flow_table * mlx5_create_flow_table (struct mlx5_flow_namespace * ns ,
514537 int prio ,
515538 int max_fte )
@@ -526,22 +549,23 @@ struct mlx5_flow_table *mlx5_create_flow_table(struct mlx5_flow_namespace *ns,
526549 return ERR_PTR (- ENODEV );
527550 }
528551
552+ mutex_lock (& root -> chain_lock );
529553 fs_prio = find_prio (ns , prio );
530- if (!fs_prio )
531- return ERR_PTR ( - EINVAL ) ;
532-
533- lock_ref_node ( & fs_prio -> node );
554+ if (!fs_prio ) {
555+ err = - EINVAL ;
556+ goto unlock_root ;
557+ }
534558 if (fs_prio -> num_ft == fs_prio -> max_ft ) {
535559 err = - ENOSPC ;
536- goto unlock_prio ;
560+ goto unlock_root ;
537561 }
538562
539563 ft = alloc_flow_table (find_next_free_level (fs_prio ),
540564 roundup_pow_of_two (max_fte ),
541565 root -> table_type );
542566 if (!ft ) {
543567 err = - ENOMEM ;
544- goto unlock_prio ;
568+ goto unlock_root ;
545569 }
546570
547571 tree_init_node (& ft -> node , 1 , del_flow_table );
@@ -551,15 +575,25 @@ struct mlx5_flow_table *mlx5_create_flow_table(struct mlx5_flow_namespace *ns,
551575 if (err )
552576 goto free_ft ;
553577
578+ if (MLX5_CAP_FLOWTABLE (root -> dev ,
579+ flow_table_properties_nic_receive .modify_root )) {
580+ err = update_root_ft_create (ft , fs_prio );
581+ if (err )
582+ goto destroy_ft ;
583+ }
584+ lock_ref_node (& fs_prio -> node );
554585 tree_add_node (& ft -> node , & fs_prio -> node );
555586 list_add_tail (& ft -> node .list , & fs_prio -> node .children );
556587 fs_prio -> num_ft ++ ;
557588 unlock_ref_node (& fs_prio -> node );
589+ mutex_unlock (& root -> chain_lock );
558590 return ft ;
591+ destroy_ft :
592+ mlx5_cmd_destroy_flow_table (root -> dev , ft );
559593free_ft :
560594 kfree (ft );
561- unlock_prio :
562- unlock_ref_node ( & fs_prio -> node );
595+ unlock_root :
596+ mutex_unlock ( & root -> chain_lock );
563597 return ERR_PTR (err );
564598}
565599
@@ -899,13 +933,57 @@ void mlx5_del_flow_rule(struct mlx5_flow_rule *rule)
899933 tree_remove_node (& rule -> node );
900934}
901935
936+ /* Assuming prio->node.children(flow tables) is sorted by level */
937+ static struct mlx5_flow_table * find_next_ft (struct mlx5_flow_table * ft )
938+ {
939+ struct fs_prio * prio ;
940+
941+ fs_get_obj (prio , ft -> node .parent );
942+
943+ if (!list_is_last (& ft -> node .list , & prio -> node .children ))
944+ return list_next_entry (ft , node .list );
945+ return find_next_chained_ft (prio );
946+ }
947+
948+ static int update_root_ft_destroy (struct mlx5_flow_table * ft )
949+ {
950+ struct mlx5_flow_root_namespace * root = find_root (& ft -> node );
951+ struct mlx5_flow_table * new_root_ft = NULL ;
952+
953+ if (root -> root_ft != ft )
954+ return 0 ;
955+
956+ new_root_ft = find_next_ft (ft );
957+ if (new_root_ft ) {
958+ int err = mlx5_cmd_update_root_ft (root -> dev , new_root_ft );
959+
960+ if (err ) {
961+ mlx5_core_warn (root -> dev , "Update root flow table of id=%u failed\n" ,
962+ ft -> id );
963+ return err ;
964+ }
965+ root -> root_ft = new_root_ft ;
966+ }
967+ return 0 ;
968+ }
969+
902970int mlx5_destroy_flow_table (struct mlx5_flow_table * ft )
903971{
972+ struct mlx5_flow_root_namespace * root = find_root (& ft -> node );
973+ int err = 0 ;
974+
975+ mutex_lock (& root -> chain_lock );
976+ err = update_root_ft_destroy (ft );
977+ if (err ) {
978+ mutex_unlock (& root -> chain_lock );
979+ return err ;
980+ }
904981 if (tree_remove_node (& ft -> node ))
905982 mlx5_core_warn (get_dev (& ft -> node ), "Flow table %d wasn't destroyed, refcount > 1\n" ,
906983 ft -> id );
984+ mutex_unlock (& root -> chain_lock );
907985
908- return 0 ;
986+ return err ;
909987}
910988
911989void mlx5_destroy_flow_group (struct mlx5_flow_group * fg )
@@ -1072,6 +1150,7 @@ static struct mlx5_flow_root_namespace *create_root_ns(struct mlx5_core_dev *dev
10721150
10731151 ns = & root_ns -> ns ;
10741152 fs_init_namespace (ns );
1153+ mutex_init (& root_ns -> chain_lock );
10751154 tree_init_node (& ns -> node , 1 , NULL );
10761155 tree_add_node (& ns -> node , NULL );
10771156
0 commit comments