@@ -1441,47 +1441,87 @@ static bool dest_is_valid(struct mlx5_flow_destination *dest,
14411441 return true;
14421442}
14431443
1444- static struct mlx5_flow_handle *
1445- try_add_to_existing_fg (struct mlx5_flow_table * ft ,
1446- struct mlx5_flow_spec * spec ,
1447- struct mlx5_flow_act * flow_act ,
1448- struct mlx5_flow_destination * dest ,
1449- int dest_num )
1450- {
1444+ struct match_list {
1445+ struct list_head list ;
14511446 struct mlx5_flow_group * g ;
1452- struct mlx5_flow_handle * rule ;
1447+ };
1448+
1449+ struct match_list_head {
1450+ struct list_head list ;
1451+ struct match_list first ;
1452+ };
1453+
1454+ static void free_match_list (struct match_list_head * head )
1455+ {
1456+ if (!list_empty (& head -> list )) {
1457+ struct match_list * iter , * match_tmp ;
1458+
1459+ list_del (& head -> first .list );
1460+ list_for_each_entry_safe (iter , match_tmp , & head -> list ,
1461+ list ) {
1462+ list_del (& iter -> list );
1463+ kfree (iter );
1464+ }
1465+ }
1466+ }
1467+
1468+ static int build_match_list (struct match_list_head * match_head ,
1469+ struct mlx5_flow_table * ft ,
1470+ struct mlx5_flow_spec * spec )
1471+ {
14531472 struct rhlist_head * tmp , * list ;
1454- struct match_list {
1455- struct list_head list ;
1456- struct mlx5_flow_group * g ;
1457- } match_list , * iter ;
1458- LIST_HEAD (match_head );
1473+ struct mlx5_flow_group * g ;
1474+ int err = 0 ;
14591475
14601476 rcu_read_lock ();
1477+ INIT_LIST_HEAD (& match_head -> list );
14611478 /* Collect all fgs which has a matching match_criteria */
14621479 list = rhltable_lookup (& ft -> fgs_hash , spec , rhash_fg );
1480+ /* RCU is atomic, we can't execute FW commands here */
14631481 rhl_for_each_entry_rcu (g , tmp , list , hash ) {
14641482 struct match_list * curr_match ;
14651483
1466- if (likely (list_empty (& match_head ))) {
1467- match_list .g = g ;
1468- list_add_tail (& match_list .list , & match_head );
1484+ if (likely (list_empty (& match_head -> list ))) {
1485+ match_head -> first .g = g ;
1486+ list_add_tail (& match_head -> first .list ,
1487+ & match_head -> list );
14691488 continue ;
14701489 }
1471- curr_match = kmalloc (sizeof (* curr_match ), GFP_ATOMIC );
14721490
1491+ curr_match = kmalloc (sizeof (* curr_match ), GFP_ATOMIC );
14731492 if (!curr_match ) {
1474- rcu_read_unlock ( );
1475- rule = ERR_PTR ( - ENOMEM ) ;
1476- goto free_list ;
1493+ free_match_list ( match_head );
1494+ err = - ENOMEM ;
1495+ goto out ;
14771496 }
14781497 curr_match -> g = g ;
1479- list_add_tail (& curr_match -> list , & match_head );
1498+ list_add_tail (& curr_match -> list , & match_head -> list );
14801499 }
1500+ out :
14811501 rcu_read_unlock ();
1502+ return err ;
1503+ }
1504+
1505+ static struct mlx5_flow_handle *
1506+ try_add_to_existing_fg (struct mlx5_flow_table * ft ,
1507+ struct mlx5_flow_spec * spec ,
1508+ struct mlx5_flow_act * flow_act ,
1509+ struct mlx5_flow_destination * dest ,
1510+ int dest_num )
1511+ {
1512+ struct mlx5_flow_group * g ;
1513+ struct mlx5_flow_handle * rule ;
1514+ struct match_list_head match_head ;
1515+ struct match_list * iter ;
1516+ int err ;
1517+
1518+ /* Collect all fgs which has a matching match_criteria */
1519+ err = build_match_list (& match_head , ft , spec );
1520+ if (err )
1521+ return ERR_PTR (err );
14821522
14831523 /* Try to find a fg that already contains a matching fte */
1484- list_for_each_entry (iter , & match_head , list ) {
1524+ list_for_each_entry (iter , & match_head . list , list ) {
14851525 struct fs_fte * fte ;
14861526
14871527 g = iter -> g ;
@@ -1500,7 +1540,7 @@ try_add_to_existing_fg(struct mlx5_flow_table *ft,
15001540 /* No group with matching fte found. Try to add a new fte to any
15011541 * matching fg.
15021542 */
1503- list_for_each_entry (iter , & match_head , list ) {
1543+ list_for_each_entry (iter , & match_head . list , list ) {
15041544 g = iter -> g ;
15051545
15061546 nested_lock_ref_node (& g -> node , FS_MUTEX_PARENT );
@@ -1516,19 +1556,7 @@ try_add_to_existing_fg(struct mlx5_flow_table *ft,
15161556 rule = ERR_PTR (- ENOENT );
15171557
15181558free_list :
1519- if (!list_empty (& match_head )) {
1520- struct match_list * match_tmp ;
1521-
1522- /* The most common case is having one FG. Since we want to
1523- * optimize this case, we save the first on the stack.
1524- * Therefore, no need to free it.
1525- */
1526- list_del (& list_first_entry (& match_head , typeof (* iter ), list )-> list );
1527- list_for_each_entry_safe (iter , match_tmp , & match_head , list ) {
1528- list_del (& iter -> list );
1529- kfree (iter );
1530- }
1531- }
1559+ free_match_list (& match_head );
15321560
15331561 return rule ;
15341562}
0 commit comments