@@ -1441,47 +1441,87 @@ static bool dest_is_valid(struct mlx5_flow_destination *dest,
1441
1441
return true;
1442
1442
}
1443
1443
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 ;
1451
1446
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
+ {
1453
1472
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 ;
1459
1475
1460
1476
rcu_read_lock ();
1477
+ INIT_LIST_HEAD (& match_head -> list );
1461
1478
/* Collect all fgs which has a matching match_criteria */
1462
1479
list = rhltable_lookup (& ft -> fgs_hash , spec , rhash_fg );
1480
+ /* RCU is atomic, we can't execute FW commands here */
1463
1481
rhl_for_each_entry_rcu (g , tmp , list , hash ) {
1464
1482
struct match_list * curr_match ;
1465
1483
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 );
1469
1488
continue ;
1470
1489
}
1471
- curr_match = kmalloc (sizeof (* curr_match ), GFP_ATOMIC );
1472
1490
1491
+ curr_match = kmalloc (sizeof (* curr_match ), GFP_ATOMIC );
1473
1492
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 ;
1477
1496
}
1478
1497
curr_match -> g = g ;
1479
- list_add_tail (& curr_match -> list , & match_head );
1498
+ list_add_tail (& curr_match -> list , & match_head -> list );
1480
1499
}
1500
+ out :
1481
1501
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 );
1482
1522
1483
1523
/* 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 ) {
1485
1525
struct fs_fte * fte ;
1486
1526
1487
1527
g = iter -> g ;
@@ -1500,7 +1540,7 @@ try_add_to_existing_fg(struct mlx5_flow_table *ft,
1500
1540
/* No group with matching fte found. Try to add a new fte to any
1501
1541
* matching fg.
1502
1542
*/
1503
- list_for_each_entry (iter , & match_head , list ) {
1543
+ list_for_each_entry (iter , & match_head . list , list ) {
1504
1544
g = iter -> g ;
1505
1545
1506
1546
nested_lock_ref_node (& g -> node , FS_MUTEX_PARENT );
@@ -1516,19 +1556,7 @@ try_add_to_existing_fg(struct mlx5_flow_table *ft,
1516
1556
rule = ERR_PTR (- ENOENT );
1517
1557
1518
1558
free_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 );
1532
1560
1533
1561
return rule ;
1534
1562
}
0 commit comments