diff options
author | Kalderon, Michal <Michal.Kalderon@cavium.com> | 2017-07-26 14:41:55 +0300 |
---|---|---|
committer | Doug Ledford <dledford@redhat.com> | 2017-08-18 19:26:38 +0300 |
commit | de0089e692a92ce5180eec6a79f1f79153e3c669 (patch) | |
tree | fecb49ed3138f2ebf5cac74f3626578e07858bd2 /drivers/infiniband/hw/qedr/verbs.c | |
parent | fb1a22be9d32675ba140a4e1438e5e52c6d5694e (diff) | |
download | linux-de0089e692a92ce5180eec6a79f1f79153e3c669.tar.xz |
RDMA/qedr: Add iWARP connection management qp related callbacks
This patch implements the following iWARP callbacks:
qp_add_ref
qp_rem_ref
get_qp
Signed-off-by: Michal Kalderon <Michal.Kalderon@cavium.com>
Signed-off-by: Ram Amrani <Ram.Amrani@cavium.com>
Signed-off-by: Ariel Elior <Ariel.Elior@cavium.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
Diffstat (limited to 'drivers/infiniband/hw/qedr/verbs.c')
-rw-r--r-- | drivers/infiniband/hw/qedr/verbs.c | 38 |
1 files changed, 36 insertions, 2 deletions
diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c index 237ae5e40e76..2d8d031ca713 100644 --- a/drivers/infiniband/hw/qedr/verbs.c +++ b/drivers/infiniband/hw/qedr/verbs.c @@ -1280,6 +1280,7 @@ static void qedr_set_common_qp_params(struct qedr_dev *dev, struct ib_qp_init_attr *attrs) { spin_lock_init(&qp->q_lock); + atomic_set(&qp->refcnt, 1); qp->pd = pd; qp->qp_type = attrs->qp_type; qp->max_inline_data = attrs->cap.max_inline_data; @@ -1350,6 +1351,33 @@ static inline void qedr_qp_user_print(struct qedr_dev *dev, struct qedr_qp *qp) qp->usq.buf_len, qp->urq.buf_addr, qp->urq.buf_len); } +static int qedr_idr_add(struct qedr_dev *dev, void *ptr, u32 id) +{ + int rc; + + if (!rdma_protocol_iwarp(&dev->ibdev, 1)) + return 0; + + idr_preload(GFP_KERNEL); + spin_lock_irq(&dev->idr_lock); + + rc = idr_alloc(&dev->qpidr, ptr, id, id + 1, GFP_ATOMIC); + + spin_unlock_irq(&dev->idr_lock); + idr_preload_end(); + + return rc < 0 ? rc : 0; +} + +static void qedr_idr_remove(struct qedr_dev *dev, u32 id) +{ + if (!rdma_protocol_iwarp(&dev->ibdev, 1)) + return; + + spin_lock_irq(&dev->idr_lock); + idr_remove(&dev->qpidr, id); + spin_unlock_irq(&dev->idr_lock); +} static void qedr_cleanup_user(struct qedr_dev *dev, struct qedr_qp *qp) { if (qp->usq.umem) @@ -1700,6 +1728,10 @@ struct ib_qp *qedr_create_qp(struct ib_pd *ibpd, qp->ibqp.qp_num = qp->qp_id; + rc = qedr_idr_add(dev, qp, qp->qp_id); + if (rc) + goto err; + return &qp->ibqp; err: @@ -2232,8 +2264,10 @@ int qedr_destroy_qp(struct ib_qp *ibqp) qedr_free_qp_resources(dev, qp); - kfree(qp); - + if (atomic_dec_and_test(&qp->refcnt)) { + qedr_idr_remove(dev, qp->qp_id); + kfree(qp); + } return rc; } |