From 1f0f4c3cde42e646c537d8d759d678f44c306641 Mon Sep 17 00:00:00 2001 From: Davide Rossetti Date: Mon, 23 Jan 2017 17:22:47 -0800 Subject: [PATCH] add peer memory support to create_user_qp --- drivers/infiniband/hw/mlx5/mlx5_ib.h | 3 ++ drivers/infiniband/hw/mlx5/qp.c | 44 ++++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h index 5af85e1..9c9aca3 100644 --- a/drivers/infiniband/hw/mlx5/mlx5_ib.h +++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h @@ -332,6 +332,9 @@ struct mlx5_ib_qp { /* Store signature errors */ bool signature_en; + atomic_t invalidated; + struct completion invalidation_comp; + #ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING /* * A flag that is true for QP's that are in a state that doesn't diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c index 6eefcac..67b76ab 100644 --- a/drivers/infiniband/hw/mlx5/qp.c +++ b/drivers/infiniband/hw/mlx5/qp.c @@ -850,6 +850,36 @@ static int create_user_rq(struct mlx5_ib_dev *dev, struct ib_pd *pd, return err; } +static void mlx5_qp_invalidate_umem(void *invalidation_cookie, + struct ib_umem *umem, + unsigned long addr, size_t size) +{ + struct mlx5_ib_qp *qp = (struct mlx5_ib_qp *)invalidation_cookie; + + printk(KERN_ERR "WARN mlx5_qp_invalidate_umem qp=%p umem=%p\n", qp, umem); + + /* This function is called under client peer lock so its resources are race protected */ + if (atomic_inc_return(&qp->invalidated) > 1) { + printk(KERN_ERR "invalidation is already in-flight\n"); + umem->invalidation_ctx->inflight_invalidation = 1; + return; + } + + if (umem != qp->umem) { + printk(KERN_ERR "ERR unexpected qp->umem=%p != umem=%p\n", qp->umem, umem); + } else { + qp->umem = NULL; + } + + umem->invalidation_ctx->peer_callback = 1; + // TODO: + // - free MTTs related, etc.. + // - make it ODP friendly ? + printk(KERN_ERR "releasing umem=%p\n", umem); + ib_umem_release(umem); + complete(&qp->invalidation_comp); +} + static int create_user_qp(struct mlx5_ib_dev *dev, struct ib_pd *pd, struct mlx5_ib_qp *qp, struct ib_udata *udata, struct ib_exp_qp_init_attr *attr, @@ -927,13 +957,17 @@ static int create_user_qp(struct mlx5_ib_dev *dev, struct ib_pd *pd, goto err_uuar; if (ucmd->buf_addr && qp->buf_size) { - qp->umem = ib_umem_get(pd->uobject->context, ucmd->buf_addr, - qp->buf_size, 0, 0); + //qp->umem = ib_umem_get(pd->uobject->context, ucmd->buf_addr, + // qp->buf_size, 0, 0); + qp->umem = ib_umem_get_ex(pd->uobject->context, ucmd->buf_addr, + qp->buf_size, 0, 0, 1); if (IS_ERR(qp->umem)) { mlx5_ib_warn(dev, "umem_get failed\n"); err = PTR_ERR(qp->umem); goto err_uuar; } + if (qp->umem->ib_peer_mem) + printk(KERN_ERR "INFO create_user_qp got peer_mem, qp=%p umem=%p\n", qp, qp->umem); } else { qp->umem = NULL; } @@ -1007,6 +1041,12 @@ static int create_user_qp(struct mlx5_ib_dev *dev, struct ib_pd *pd, } qp->create_type = MLX5_QP_USER; + atomic_set(&qp->invalidated, 0); + if (qp->umem && qp->umem->ib_peer_mem) { + init_completion(&qp->invalidation_comp); + ib_umem_activate_invalidation_notifier(qp->umem, mlx5_qp_invalidate_umem, qp); + } + return 0; err_unmap: