net/mlx5: Add new list to store deleted flow counters
[sfrench/cifs-2.6.git] / drivers / net / ethernet / mellanox / mlx5 / core / fs_counters.c
index d996d6cf9e198a59e49c4e2f7b40f118a51af8ac..f1266f215a31319425d8111ecc804434817964c4 100644 (file)
@@ -58,7 +58,7 @@
  *   - spawn thread to do the actual destroy
  *
  * - destroy (user context)
- *   - mark a counter as deleted
+ *   - add a counter to lockless dellist
  *   - spawn thread to do the actual del
  *
  * - dump (user context)
@@ -171,9 +171,8 @@ static void mlx5_fc_stats_work(struct work_struct *work)
                                                 priv.fc_stats.work.work);
        struct mlx5_fc_stats *fc_stats = &dev->priv.fc_stats;
        struct llist_node *tmplist = llist_del_all(&fc_stats->addlist);
+       struct mlx5_fc *counter = NULL, *last = NULL, *tmp;
        unsigned long now = jiffies;
-       struct mlx5_fc *counter = NULL;
-       struct mlx5_fc *last = NULL;
        struct rb_node *node;
 
        if (tmplist || !RB_EMPTY_ROOT(&fc_stats->counters))
@@ -183,26 +182,17 @@ static void mlx5_fc_stats_work(struct work_struct *work)
        llist_for_each_entry(counter, tmplist, addlist)
                mlx5_fc_stats_insert(&fc_stats->counters, counter);
 
-       node = rb_first(&fc_stats->counters);
-       while (node) {
-               counter = rb_entry(node, struct mlx5_fc, node);
-
-               node = rb_next(node);
-
-               if (counter->deleted) {
-                       rb_erase(&counter->node, &fc_stats->counters);
-
-                       mlx5_cmd_fc_free(dev, counter->id);
-
-                       kfree(counter);
-                       continue;
-               }
+       tmplist = llist_del_all(&fc_stats->dellist);
+       llist_for_each_entry_safe(counter, tmp, tmplist, dellist) {
+               rb_erase(&counter->node, &fc_stats->counters);
 
-               last = counter;
+               mlx5_free_fc(dev, counter);
        }
 
-       if (time_before(now, fc_stats->next_query) || !last)
+       node = rb_last(&fc_stats->counters);
+       if (time_before(now, fc_stats->next_query) || !node)
                return;
+       last = rb_entry(node, struct mlx5_fc, node);
 
        node = rb_first(&fc_stats->counters);
        while (node) {
@@ -254,13 +244,12 @@ void mlx5_fc_destroy(struct mlx5_core_dev *dev, struct mlx5_fc *counter)
                return;
 
        if (counter->aging) {
-               counter->deleted = true;
+               llist_add(&counter->dellist, &fc_stats->dellist);
                mod_delayed_work(fc_stats->wq, &fc_stats->work, 0);
                return;
        }
 
-       mlx5_cmd_fc_free(dev, counter->id);
-       kfree(counter);
+       mlx5_free_fc(dev, counter);
 }
 EXPORT_SYMBOL(mlx5_fc_destroy);
 
@@ -270,6 +259,7 @@ int mlx5_init_fc_stats(struct mlx5_core_dev *dev)
 
        fc_stats->counters = RB_ROOT;
        init_llist_head(&fc_stats->addlist);
+       init_llist_head(&fc_stats->dellist);
 
        fc_stats->wq = create_singlethread_workqueue("mlx5_fc");
        if (!fc_stats->wq)