@@ -629,6 +629,8 @@ struct mlx5_ib_mkey {
unsigned int ndescs;
struct wait_queue_head wait;
refcount_t usecount;
+ /* User Mkey must hold either a cache_key or a cache_ent. */
+ struct mlx5r_cache_rb_key rb_key;
struct mlx5_cache_ent *cache_ent;
};
@@ -812,6 +812,7 @@ struct mlx5_ib_mr *mlx5_mr_cache_alloc(struct mlx5_ib_dev *dev, u8 access_mode,
return ERR_PTR(err);
}
mr->mmkey.ndescs = ndescs;
+ mr->mmkey.rb_key = rb_key;
}
mr->mmkey.type = MLX5_MKEY_MR;
init_waitqueue_head(&mr->mmkey.wait);
@@ -1723,6 +1724,42 @@ mlx5_free_priv_descs(struct mlx5_ib_mr *mr)
}
}
+static int cache_ent_find_and_store(struct mlx5_ib_dev *dev,
+ struct mlx5_ib_mr *mr)
+{
+ struct mlx5_mkey_cache *cache = &dev->cache;
+ struct mlx5_cache_ent *ent;
+ struct rb_node *node;
+
+ if (mr->mmkey.cache_ent) {
+ xa_lock_irq(&mr->mmkey.cache_ent->mkeys);
+ mr->mmkey.cache_ent->in_use--;
+ xa_unlock_irq(&mr->mmkey.cache_ent->mkeys);
+ goto end;
+ }
+
+ mutex_lock(&cache->rb_lock);
+ node = mlx5_cache_find_smallest_ent(&dev->cache, mr->mmkey.rb_key);
+ mutex_unlock(&cache->rb_lock);
+ if (node) {
+ ent = rb_entry(node, struct mlx5_cache_ent, node);
+ if (ent->rb_key.ndescs == mr->mmkey.rb_key.ndescs) {
+ mr->mmkey.cache_ent = ent;
+ goto end;
+ }
+ }
+
+ ent = mlx5r_cache_create_ent(dev, mr->mmkey.rb_key);
+ if (IS_ERR(ent))
+ return PTR_ERR(ent);
+
+ mr->mmkey.cache_ent = ent;
+
+end:
+ return push_mkey(mr->mmkey.cache_ent, false,
+ xa_mk_value(mr->mmkey.key));
+}
+
int mlx5_ib_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata)
{
struct mlx5_ib_mr *mr = to_mmr(ibmr);
@@ -1768,16 +1805,11 @@ int mlx5_ib_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata)
}
/* Stop DMA */
- if (mr->mmkey.cache_ent) {
- xa_lock_irq(&mr->mmkey.cache_ent->mkeys);
- mr->mmkey.cache_ent->in_use--;
- xa_unlock_irq(&mr->mmkey.cache_ent->mkeys);
-
+ if (mr->umem && mlx5r_umr_can_load_pas(dev, mr->umem->length))
if (mlx5r_umr_revoke_mr(mr) ||
- push_mkey(mr->mmkey.cache_ent, false,
- xa_mk_value(mr->mmkey.key)))
+ cache_ent_find_and_store(dev, mr))
mr->mmkey.cache_ent = NULL;
- }
+
if (!mr->mmkey.cache_ent) {
rc = destroy_mkey(to_mdev(mr->ibmr.device), mr);
if (rc)