net/mlx5: Convert mkey_table to XArray
authorMatthew Wilcox <willy@infradead.org>
Thu, 20 Jun 2019 07:03:47 +0000 (07:03 +0000)
committerSaeed Mahameed <saeedm@mellanox.com>
Mon, 24 Jun 2019 23:44:40 +0000 (16:44 -0700)
The lock protecting the data structure does not need to be an rwlock.  The
only read access to the lock is in an error path, and if that's limiting
your scalability, you have bigger performance problems.

Eliminate mlx5_mkey_table in favour of using the xarray directly.
reg_mr_callback must use GFP_ATOMIC for allocating XArray nodes as it may
be called in interrupt context.

This also fixes a minor bug where SRCU locking was being used on the radix
tree read side, when RCU was needed too.

Signed-off-by: Matthew Wilcox <willy@infradead.org>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
drivers/infiniband/hw/mlx5/cq.c
drivers/infiniband/hw/mlx5/devx.c
drivers/infiniband/hw/mlx5/mr.c
drivers/infiniband/hw/mlx5/odp.c
drivers/net/ethernet/mellanox/mlx5/core/mr.c
include/linux/mlx5/driver.h
include/linux/mlx5/qp.h

index 2e2e65f00257597be9e02d53012f0c493fc1a2cb..0220736b073e6355f0fc33baddf726a7a27ae14a 100644 (file)
@@ -522,9 +522,9 @@ repoll:
        case MLX5_CQE_SIG_ERR:
                sig_err_cqe = (struct mlx5_sig_err_cqe *)cqe64;
 
-               read_lock(&dev->mdev->priv.mkey_table.lock);
-               mmkey = __mlx5_mr_lookup(dev->mdev,
-                                        mlx5_base_mkey(be32_to_cpu(sig_err_cqe->mkey)));
+               xa_lock(&dev->mdev->priv.mkey_table);
+               mmkey = xa_load(&dev->mdev->priv.mkey_table,
+                               mlx5_base_mkey(be32_to_cpu(sig_err_cqe->mkey)));
                mr = to_mibmr(mmkey);
                get_sig_err_item(sig_err_cqe, &mr->sig->err_item);
                mr->sig->sig_err_exists = true;
@@ -537,7 +537,7 @@ repoll:
                             mr->sig->err_item.expected,
                             mr->sig->err_item.actual);
 
-               read_unlock(&dev->mdev->priv.mkey_table.lock);
+               xa_unlock(&dev->mdev->priv.mkey_table);
                goto repoll;
        }
 
index 80b42d0693286084bcc1670f838dff218e00bc0e..931f587dfb8fda45476babceeee2b3be450ffaec 100644 (file)
@@ -1043,13 +1043,10 @@ static int devx_handle_mkey_indirect(struct devx_obj *obj,
                                     struct mlx5_ib_dev *dev,
                                     void *in, void *out)
 {
-       struct mlx5_mkey_table *table = &dev->mdev->priv.mkey_table;
        struct mlx5_ib_devx_mr *devx_mr = &obj->devx_mr;
-       unsigned long flags;
        struct mlx5_core_mkey *mkey;
        void *mkc;
        u8 key;
-       int err;
 
        mkey = &devx_mr->mmkey;
        mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);
@@ -1062,11 +1059,8 @@ static int devx_handle_mkey_indirect(struct devx_obj *obj,
        mkey->pd = MLX5_GET(mkc, mkc, pd);
        devx_mr->ndescs = MLX5_GET(mkc, mkc, translations_octword_size);
 
-       write_lock_irqsave(&table->lock, flags);
-       err = radix_tree_insert(&table->tree, mlx5_base_mkey(mkey->key),
-                               mkey);
-       write_unlock_irqrestore(&table->lock, flags);
-       return err;
+       return xa_err(xa_store(&dev->mdev->priv.mkey_table,
+                              mlx5_base_mkey(mkey->key), mkey, GFP_KERNEL));
 }
 
 static int devx_handle_mkey_create(struct mlx5_ib_dev *dev,
@@ -1117,12 +1111,8 @@ static void devx_free_indirect_mkey(struct rcu_head *rcu)
  */
 static void devx_cleanup_mkey(struct devx_obj *obj)
 {
-       struct mlx5_mkey_table *table = &obj->mdev->priv.mkey_table;
-       unsigned long flags;
-
-       write_lock_irqsave(&table->lock, flags);
-       radix_tree_delete(&table->tree, mlx5_base_mkey(obj->devx_mr.mmkey.key));
-       write_unlock_irqrestore(&table->lock, flags);
+       xa_erase(&obj->mdev->priv.mkey_table,
+                mlx5_base_mkey(obj->devx_mr.mmkey.key));
 }
 
 static int devx_obj_cleanup(struct ib_uobject *uobject,
index 5f09699fab984ed9179d6bd0775377742f0f6ddc..83b452d977d496c94f69114fe5ef4b0cb899fb8b 100644 (file)
@@ -130,7 +130,7 @@ static void reg_mr_callback(int status, struct mlx5_async_work *context)
        struct mlx5_cache_ent *ent = &cache->ent[c];
        u8 key;
        unsigned long flags;
-       struct mlx5_mkey_table *table = &dev->mdev->priv.mkey_table;
+       struct xarray *mkeys = &dev->mdev->priv.mkey_table;
        int err;
 
        spin_lock_irqsave(&ent->lock, flags);
@@ -158,12 +158,12 @@ static void reg_mr_callback(int status, struct mlx5_async_work *context)
        ent->size++;
        spin_unlock_irqrestore(&ent->lock, flags);
 
-       write_lock_irqsave(&table->lock, flags);
-       err = radix_tree_insert(&table->tree, mlx5_base_mkey(mr->mmkey.key),
-                               &mr->mmkey);
+       xa_lock_irqsave(mkeys, flags);
+       err = xa_err(__xa_store(mkeys, mlx5_base_mkey(mr->mmkey.key),
+                               &mr->mmkey, GFP_ATOMIC));
+       xa_unlock_irqrestore(mkeys, flags);
        if (err)
                pr_err("Error inserting to mkey tree. 0x%x\n", -err);
-       write_unlock_irqrestore(&table->lock, flags);
 
        if (!completion_done(&ent->compl))
                complete(&ent->compl);
index 12ccee1eb047f20a625e6e132c12b8a93fa01f28..c594489eb2d7b7771eccbc2a76512f94b01d5cbe 100644 (file)
@@ -768,7 +768,7 @@ static int pagefault_single_data_segment(struct mlx5_ib_dev *dev,
        bcnt -= *bytes_committed;
 
 next_mr:
-       mmkey = __mlx5_mr_lookup(dev->mdev, mlx5_base_mkey(key));
+       mmkey = xa_load(&dev->mdev->priv.mkey_table, mlx5_base_mkey(key));
        if (!mkey_is_eq(mmkey, key)) {
                mlx5_ib_dbg(dev, "failed to find mkey %x\n", key);
                ret = -EFAULT;
@@ -1686,8 +1686,8 @@ static void num_pending_prefetch_dec(struct mlx5_ib_dev *dev,
                struct mlx5_core_mkey *mmkey;
                struct mlx5_ib_mr *mr;
 
-               mmkey = __mlx5_mr_lookup(dev->mdev,
-                                        mlx5_base_mkey(sg_list[i].lkey));
+               mmkey = xa_load(&dev->mdev->priv.mkey_table,
+                               mlx5_base_mkey(sg_list[i].lkey));
                mr = container_of(mmkey, struct mlx5_ib_mr, mmkey);
                atomic_dec(&mr->num_pending_prefetch);
        }
@@ -1706,8 +1706,8 @@ static bool num_pending_prefetch_inc(struct ib_pd *pd,
                struct mlx5_core_mkey *mmkey;
                struct mlx5_ib_mr *mr;
 
-               mmkey = __mlx5_mr_lookup(dev->mdev,
-                                        mlx5_base_mkey(sg_list[i].lkey));
+               mmkey = xa_load(&dev->mdev->priv.mkey_table,
+                               mlx5_base_mkey(sg_list[i].lkey));
                if (!mmkey || mmkey->key != sg_list[i].lkey) {
                        ret = false;
                        break;
index ea744d8466eab528224a466b3e6e4cb3952817a9..9231b39d18b21c11f971773fa65376f442d010ae 100644 (file)
 
 void mlx5_init_mkey_table(struct mlx5_core_dev *dev)
 {
-       struct mlx5_mkey_table *table = &dev->priv.mkey_table;
-
-       memset(table, 0, sizeof(*table));
-       rwlock_init(&table->lock);
-       INIT_RADIX_TREE(&table->tree, GFP_ATOMIC);
+       xa_init_flags(&dev->priv.mkey_table, XA_FLAGS_LOCK_IRQ);
 }
 
 void mlx5_cleanup_mkey_table(struct mlx5_core_dev *dev)
 {
+       WARN_ON(!xa_empty(&dev->priv.mkey_table));
 }
 
 int mlx5_core_create_mkey_cb(struct mlx5_core_dev *dev,
@@ -56,8 +53,8 @@ int mlx5_core_create_mkey_cb(struct mlx5_core_dev *dev,
                             mlx5_async_cbk_t callback,
                             struct mlx5_async_work *context)
 {
-       struct mlx5_mkey_table *table = &dev->priv.mkey_table;
        u32 lout[MLX5_ST_SZ_DW(create_mkey_out)] = {0};
+       struct xarray *mkeys = &dev->priv.mkey_table;
        u32 mkey_index;
        void *mkc;
        int err;
@@ -88,12 +85,10 @@ int mlx5_core_create_mkey_cb(struct mlx5_core_dev *dev,
        mlx5_core_dbg(dev, "out 0x%x, key 0x%x, mkey 0x%x\n",
                      mkey_index, key, mkey->key);
 
-       /* connect to mkey tree */
-       write_lock_irq(&table->lock);
-       err = radix_tree_insert(&table->tree, mlx5_base_mkey(mkey->key), mkey);
-       write_unlock_irq(&table->lock);
+       err = xa_err(xa_store_irq(mkeys, mlx5_base_mkey(mkey->key), mkey,
+                                 GFP_KERNEL));
        if (err) {
-               mlx5_core_warn(dev, "failed radix tree insert of mkey 0x%x, %d\n",
+               mlx5_core_warn(dev, "failed xarray insert of mkey 0x%x, %d\n",
                               mlx5_base_mkey(mkey->key), err);
                mlx5_core_destroy_mkey(dev, mkey);
        }
@@ -114,17 +109,17 @@ EXPORT_SYMBOL(mlx5_core_create_mkey);
 int mlx5_core_destroy_mkey(struct mlx5_core_dev *dev,
                           struct mlx5_core_mkey *mkey)
 {
-       struct mlx5_mkey_table *table = &dev->priv.mkey_table;
        u32 out[MLX5_ST_SZ_DW(destroy_mkey_out)] = {0};
        u32 in[MLX5_ST_SZ_DW(destroy_mkey_in)]   = {0};
+       struct xarray *mkeys = &dev->priv.mkey_table;
        struct mlx5_core_mkey *deleted_mkey;
        unsigned long flags;
 
-       write_lock_irqsave(&table->lock, flags);
-       deleted_mkey = radix_tree_delete(&table->tree, mlx5_base_mkey(mkey->key));
-       write_unlock_irqrestore(&table->lock, flags);
+       xa_lock_irqsave(mkeys, flags);
+       deleted_mkey = __xa_erase(mkeys, mlx5_base_mkey(mkey->key));
+       xa_unlock_irqrestore(mkeys, flags);
        if (!deleted_mkey) {
-               mlx5_core_dbg(dev, "failed radix tree delete of mkey 0x%x\n",
+               mlx5_core_dbg(dev, "failed xarray delete of mkey 0x%x\n",
                              mlx5_base_mkey(mkey->key));
                return -ENOENT;
        }
index d8ab633406c22909fda05e290be3446997eb6435..87f77ded78d4a45727bde31058256c822251d900 100644 (file)
@@ -41,7 +41,7 @@
 #include <linux/semaphore.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
-#include <linux/radix-tree.h>
+#include <linux/xarray.h>
 #include <linux/workqueue.h>
 #include <linux/mempool.h>
 #include <linux/interrupt.h>
@@ -452,13 +452,6 @@ struct mlx5_qp_table {
        struct radix_tree_root  tree;
 };
 
-struct mlx5_mkey_table {
-       /* protect radix tree
-        */
-       rwlock_t                lock;
-       struct radix_tree_root  tree;
-};
-
 struct mlx5_vf_context {
        int     enabled;
        u64     port_guid;
@@ -546,9 +539,7 @@ struct mlx5_priv {
        struct dentry          *cmdif_debugfs;
        /* end: qp staff */
 
-       /* start: mkey staff */
-       struct mlx5_mkey_table  mkey_table;
-       /* end: mkey staff */
+       struct xarray           mkey_table;
 
        /* start: alloc staff */
        /* protect buffer alocation according to numa node */
index 3ba4edbd17a6713f160d870bb3cd6465823548c0..d1f353c647970a47244aedac20fb7cb20e796c4d 100644 (file)
@@ -551,11 +551,6 @@ static inline struct mlx5_core_qp *__mlx5_qp_lookup(struct mlx5_core_dev *dev, u
        return radix_tree_lookup(&dev->priv.qp_table.tree, qpn);
 }
 
-static inline struct mlx5_core_mkey *__mlx5_mr_lookup(struct mlx5_core_dev *dev, u32 key)
-{
-       return radix_tree_lookup(&dev->priv.mkey_table.tree, key);
-}
-
 int mlx5_core_create_dct(struct mlx5_core_dev *dev,
                         struct mlx5_core_dct *qp,
                         u32 *in, int inlen,