]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commitdiff
IB/mlx5: Only synchronize RCU once when removing mkeys
authorDaniel Jurgens <danielj@mellanox.com>
Tue, 13 Mar 2018 13:18:47 +0000 (15:18 +0200)
committerDoug Ledford <dledford@redhat.com>
Wed, 14 Mar 2018 20:05:16 +0000 (16:05 -0400)
Instead synchronizing RCU in a loop when removing mkeys in a batch do it
once at the end before freeing them. The result is only waiting for one
RCU grace period instead of many serially.

Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/infiniband/hw/mlx5/mr.c

index a5fad3e87ff74c84ebf42a49ce45ec980c6f4d7d..820f93439b0cc655c6f984493903d699d3107887 100644 (file)
@@ -220,26 +220,32 @@ static void remove_keys(struct mlx5_ib_dev *dev, int c, int num)
 {
        struct mlx5_mr_cache *cache = &dev->cache;
        struct mlx5_cache_ent *ent = &cache->ent[c];
+       struct mlx5_ib_mr *tmp_mr;
        struct mlx5_ib_mr *mr;
-       int err;
+       LIST_HEAD(del_list);
        int i;
 
        for (i = 0; i < num; i++) {
                spin_lock_irq(&ent->lock);
                if (list_empty(&ent->head)) {
                        spin_unlock_irq(&ent->lock);
-                       return;
+                       break;
                }
                mr = list_first_entry(&ent->head, struct mlx5_ib_mr, list);
-               list_del(&mr->list);
+               list_move(&mr->list, &del_list);
                ent->cur--;
                ent->size--;
                spin_unlock_irq(&ent->lock);
-               err = destroy_mkey(dev, mr);
-               if (err)
-                       mlx5_ib_warn(dev, "failed destroy mkey\n");
-               else
-                       kfree(mr);
+               mlx5_core_destroy_mkey(dev->mdev, &mr->mmkey);
+       }
+
+#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
+       synchronize_srcu(&dev->mr_srcu);
+#endif
+
+       list_for_each_entry_safe(mr, tmp_mr, &del_list, list) {
+               list_del(&mr->list);
+               kfree(mr);
        }
 }
 
@@ -562,26 +568,32 @@ static void clean_keys(struct mlx5_ib_dev *dev, int c)
 {
        struct mlx5_mr_cache *cache = &dev->cache;
        struct mlx5_cache_ent *ent = &cache->ent[c];
+       struct mlx5_ib_mr *tmp_mr;
        struct mlx5_ib_mr *mr;
-       int err;
+       LIST_HEAD(del_list);
 
        cancel_delayed_work(&ent->dwork);
        while (1) {
                spin_lock_irq(&ent->lock);
                if (list_empty(&ent->head)) {
                        spin_unlock_irq(&ent->lock);
-                       return;
+                       break;
                }
                mr = list_first_entry(&ent->head, struct mlx5_ib_mr, list);
-               list_del(&mr->list);
+               list_move(&mr->list, &del_list);
                ent->cur--;
                ent->size--;
                spin_unlock_irq(&ent->lock);
-               err = destroy_mkey(dev, mr);
-               if (err)
-                       mlx5_ib_warn(dev, "failed destroy mkey\n");
-               else
-                       kfree(mr);
+               mlx5_core_destroy_mkey(dev->mdev, &mr->mmkey);
+       }
+
+#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
+       synchronize_srcu(&dev->mr_srcu);
+#endif
+
+       list_for_each_entry_safe(mr, tmp_mr, &del_list, list) {
+               list_del(&mr->list);
+               kfree(mr);
        }
 }