diff options
author | Leon Romanovsky <leonro@nvidia.com> | 2021-07-23 14:39:50 +0300 |
---|---|---|
committer | Jason Gunthorpe <jgg@nvidia.com> | 2021-08-03 19:44:27 +0300 |
commit | 514aee660df493cd673154a6ba6bab745ec47b8c (patch) | |
tree | 7a8419624a44f617b4bfee52ba38c54bd1ab90d7 /drivers/infiniband/sw/siw | |
parent | 44da3730e046a784d088157175d9418ba60661fc (diff) | |
download | linux-514aee660df493cd673154a6ba6bab745ec47b8c.tar.xz |
RDMA: Globally allocate and release QP memory
Convert QP object to follow IB/core general allocation scheme. That
change allows us to make sure that restrack properly kref the memory.
Link: https://lore.kernel.org/r/48e767124758aeecc433360ddd85eaa6325b34d9.1627040189.git.leonro@nvidia.com
Reviewed-by: Gal Pressman <galpress@amazon.com> #efa
Tested-by: Gal Pressman <galpress@amazon.com>
Reviewed-by: Dennis Dalessandro <dennis.dalessandro@cornelisnetworks.com> #rdma and core
Tested-by: Dennis Dalessandro <dennis.dalessandro@cornelisnetworks.com>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
Tested-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Diffstat (limited to 'drivers/infiniband/sw/siw')
-rw-r--r-- | drivers/infiniband/sw/siw/siw_main.c | 1 | ||||
-rw-r--r-- | drivers/infiniband/sw/siw/siw_qp.c | 2 | ||||
-rw-r--r-- | drivers/infiniband/sw/siw/siw_verbs.c | 54 | ||||
-rw-r--r-- | drivers/infiniband/sw/siw/siw_verbs.h | 5 |
4 files changed, 26 insertions, 36 deletions
diff --git a/drivers/infiniband/sw/siw/siw_main.c b/drivers/infiniband/sw/siw/siw_main.c index cf55326f2ab4..9093e6a80b26 100644 --- a/drivers/infiniband/sw/siw/siw_main.c +++ b/drivers/infiniband/sw/siw/siw_main.c @@ -297,6 +297,7 @@ static const struct ib_device_ops siw_device_ops = { INIT_RDMA_OBJ_SIZE(ib_cq, siw_cq, base_cq), INIT_RDMA_OBJ_SIZE(ib_pd, siw_pd, base_pd), + INIT_RDMA_OBJ_SIZE(ib_qp, siw_qp, base_qp), INIT_RDMA_OBJ_SIZE(ib_srq, siw_srq, base_srq), INIT_RDMA_OBJ_SIZE(ib_ucontext, siw_ucontext, base_ucontext), }; diff --git a/drivers/infiniband/sw/siw/siw_qp.c b/drivers/infiniband/sw/siw/siw_qp.c index ddb2e66f9f13..7e01f2438afc 100644 --- a/drivers/infiniband/sw/siw/siw_qp.c +++ b/drivers/infiniband/sw/siw/siw_qp.c @@ -1344,6 +1344,4 @@ void siw_free_qp(struct kref *ref) siw_put_tx_cpu(qp->tx_cpu); atomic_dec(&sdev->num_qp); - siw_dbg_qp(qp, "free QP\n"); - kfree_rcu(qp, rcu); } diff --git a/drivers/infiniband/sw/siw/siw_verbs.c b/drivers/infiniband/sw/siw/siw_verbs.c index 3f175f220a22..1b36350601fa 100644 --- a/drivers/infiniband/sw/siw/siw_verbs.c +++ b/drivers/infiniband/sw/siw/siw_verbs.c @@ -285,16 +285,16 @@ siw_mmap_entry_insert(struct siw_ucontext *uctx, * * Create QP of requested size on given device. * - * @pd: Protection Domain + * @qp: Queue pait * @attrs: Initial QP attributes. * @udata: used to provide QP ID, SQ and RQ size back to user. */ -struct ib_qp *siw_create_qp(struct ib_pd *pd, - struct ib_qp_init_attr *attrs, - struct ib_udata *udata) +int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs, + struct ib_udata *udata) { - struct siw_qp *qp = NULL; + struct ib_pd *pd = ibqp->pd; + struct siw_qp *qp = to_siw_qp(ibqp); struct ib_device *base_dev = pd->device; struct siw_device *sdev = to_siw_dev(base_dev); struct siw_ucontext *uctx = @@ -307,17 +307,16 @@ struct ib_qp *siw_create_qp(struct ib_pd *pd, siw_dbg(base_dev, "create new QP\n"); if (attrs->create_flags) - return ERR_PTR(-EOPNOTSUPP); + return -EOPNOTSUPP; if (atomic_inc_return(&sdev->num_qp) > SIW_MAX_QP) { siw_dbg(base_dev, "too many QP's\n"); - rv = -ENOMEM; - goto err_out; + return -ENOMEM; } if (attrs->qp_type != IB_QPT_RC) { siw_dbg(base_dev, "only RC QP's supported\n"); rv = -EOPNOTSUPP; - goto err_out; + goto err_atomic; } if ((attrs->cap.max_send_wr > SIW_MAX_QP_WR) || (attrs->cap.max_recv_wr > SIW_MAX_QP_WR) || @@ -325,13 +324,13 @@ struct ib_qp *siw_create_qp(struct ib_pd *pd, (attrs->cap.max_recv_sge > SIW_MAX_SGE)) { siw_dbg(base_dev, "QP size error\n"); rv = -EINVAL; - goto err_out; + goto err_atomic; } if (attrs->cap.max_inline_data > SIW_MAX_INLINE) { siw_dbg(base_dev, "max inline send: %d > %d\n", attrs->cap.max_inline_data, (int)SIW_MAX_INLINE); rv = -EINVAL; - goto err_out; + goto err_atomic; } /* * NOTE: we allow for zero element SQ and RQ WQE's SGL's @@ -340,19 +339,15 @@ struct ib_qp *siw_create_qp(struct ib_pd *pd, if (attrs->cap.max_send_wr + attrs->cap.max_recv_wr == 0) { siw_dbg(base_dev, "QP must have send or receive queue\n"); rv = -EINVAL; - goto err_out; + goto err_atomic; } if (!attrs->send_cq || (!attrs->recv_cq && !attrs->srq)) { siw_dbg(base_dev, "send CQ or receive CQ invalid\n"); rv = -EINVAL; - goto err_out; - } - qp = kzalloc(sizeof(*qp), GFP_KERNEL); - if (!qp) { - rv = -ENOMEM; - goto err_out; + goto err_atomic; } + init_rwsem(&qp->state_lock); spin_lock_init(&qp->sq_lock); spin_lock_init(&qp->rq_lock); @@ -360,7 +355,7 @@ struct ib_qp *siw_create_qp(struct ib_pd *pd, rv = siw_qp_add(sdev, qp); if (rv) - goto err_out; + goto err_atomic; num_sqe = attrs->cap.max_send_wr; num_rqe = attrs->cap.max_recv_wr; @@ -482,23 +477,20 @@ struct ib_qp *siw_create_qp(struct ib_pd *pd, list_add_tail(&qp->devq, &sdev->qp_list); spin_unlock_irqrestore(&sdev->lock, flags); - return &qp->base_qp; + return 0; err_out_xa: xa_erase(&sdev->qp_xa, qp_id(qp)); -err_out: - if (qp) { - if (uctx) { - rdma_user_mmap_entry_remove(qp->sq_entry); - rdma_user_mmap_entry_remove(qp->rq_entry); - } - vfree(qp->sendq); - vfree(qp->recvq); - kfree(qp); + if (uctx) { + rdma_user_mmap_entry_remove(qp->sq_entry); + rdma_user_mmap_entry_remove(qp->rq_entry); } - atomic_dec(&sdev->num_qp); + vfree(qp->sendq); + vfree(qp->recvq); - return ERR_PTR(rv); +err_atomic: + atomic_dec(&sdev->num_qp); + return rv; } /* diff --git a/drivers/infiniband/sw/siw/siw_verbs.h b/drivers/infiniband/sw/siw/siw_verbs.h index 67ac08886a70..09964234f8d3 100644 --- a/drivers/infiniband/sw/siw/siw_verbs.h +++ b/drivers/infiniband/sw/siw/siw_verbs.h @@ -50,9 +50,8 @@ int siw_query_gid(struct ib_device *base_dev, u32 port, int idx, union ib_gid *gid); int siw_alloc_pd(struct ib_pd *base_pd, struct ib_udata *udata); int siw_dealloc_pd(struct ib_pd *base_pd, struct ib_udata *udata); -struct ib_qp *siw_create_qp(struct ib_pd *base_pd, - struct ib_qp_init_attr *attr, - struct ib_udata *udata); +int siw_create_qp(struct ib_qp *qp, struct ib_qp_init_attr *attr, + struct ib_udata *udata); int siw_query_qp(struct ib_qp *base_qp, struct ib_qp_attr *qp_attr, int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr); int siw_verbs_modify_qp(struct ib_qp *base_qp, struct ib_qp_attr *attr, |