Skip to content

Commit

Permalink
net/mlx5: Convert mkey_table to XArray
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Matthew Wilcox authored and Saeed Mahameed committed Jun 24, 2019
1 parent 82b11f0 commit 792c4e9
Show file tree
Hide file tree
Showing 7 changed files with 31 additions and 60 deletions.
8 changes: 4 additions & 4 deletions drivers/infiniband/hw/mlx5/cq.c
Original file line number Diff line number Diff line change
Expand Up @@ -522,9 +522,9 @@ static int mlx5_poll_one(struct mlx5_ib_cq *cq,
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;
Expand All @@ -537,7 +537,7 @@ static int mlx5_poll_one(struct mlx5_ib_cq *cq,
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;
}

Expand Down
18 changes: 4 additions & 14 deletions drivers/infiniband/hw/mlx5/devx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
10 changes: 5 additions & 5 deletions drivers/infiniband/hw/mlx5/mr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
10 changes: 5 additions & 5 deletions drivers/infiniband/hw/mlx5/odp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
Expand All @@ -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;
Expand Down
27 changes: 11 additions & 16 deletions drivers/net/ethernet/mellanox/mlx5/core/mr.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,12 @@

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,
Expand All @@ -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;
Expand Down Expand Up @@ -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);
}
Expand All @@ -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;
}
Expand Down
13 changes: 2 additions & 11 deletions include/linux/mlx5/driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 */
Expand Down
5 changes: 0 additions & 5 deletions include/linux/mlx5/qp.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 792c4e9

Please sign in to comment.