IB/mthca: Add device-specific support for resizing CQs
Add low-level driver support for resizing CQs (both kernel and userspace) to mthca. Signed-off-by: Roland Dreier <rolandd@cisco.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2004, 2005 Topspin Communications. All rights reserved.
|
||||
* Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright (c) 2005 Cisco Systems. All rights reserved.
|
||||
* Copyright (c) 2005, 2006 Cisco Systems. All rights reserved.
|
||||
* Copyright (c) 2005 Mellanox Technologies. All rights reserved.
|
||||
* Copyright (c) 2004 Voltaire, Inc. All rights reserved.
|
||||
*
|
||||
@@ -669,9 +669,9 @@ static struct ib_cq *mthca_create_cq(struct ib_device *ibdev, int entries,
|
||||
}
|
||||
|
||||
if (context) {
|
||||
cq->mr.ibmr.lkey = ucmd.lkey;
|
||||
cq->set_ci_db_index = ucmd.set_db_index;
|
||||
cq->arm_db_index = ucmd.arm_db_index;
|
||||
cq->buf.mr.ibmr.lkey = ucmd.lkey;
|
||||
cq->set_ci_db_index = ucmd.set_db_index;
|
||||
cq->arm_db_index = ucmd.arm_db_index;
|
||||
}
|
||||
|
||||
for (nent = 1; nent <= entries; nent <<= 1)
|
||||
@@ -689,6 +689,8 @@ static struct ib_cq *mthca_create_cq(struct ib_device *ibdev, int entries,
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
cq->resize_buf = NULL;
|
||||
|
||||
return &cq->ibcq;
|
||||
|
||||
err_free:
|
||||
@@ -707,6 +709,121 @@ err_unmap_set:
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
static int mthca_alloc_resize_buf(struct mthca_dev *dev, struct mthca_cq *cq,
|
||||
int entries)
|
||||
{
|
||||
int ret;
|
||||
|
||||
spin_lock_irq(&cq->lock);
|
||||
if (cq->resize_buf) {
|
||||
ret = -EBUSY;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
cq->resize_buf = kmalloc(sizeof *cq->resize_buf, GFP_ATOMIC);
|
||||
if (!cq->resize_buf) {
|
||||
ret = -ENOMEM;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
cq->resize_buf->state = CQ_RESIZE_ALLOC;
|
||||
|
||||
ret = 0;
|
||||
|
||||
unlock:
|
||||
spin_unlock_irq(&cq->lock);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = mthca_alloc_cq_buf(dev, &cq->resize_buf->buf, entries);
|
||||
if (ret) {
|
||||
spin_lock_irq(&cq->lock);
|
||||
kfree(cq->resize_buf);
|
||||
cq->resize_buf = NULL;
|
||||
spin_unlock_irq(&cq->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
cq->resize_buf->cqe = entries - 1;
|
||||
|
||||
spin_lock_irq(&cq->lock);
|
||||
cq->resize_buf->state = CQ_RESIZE_READY;
|
||||
spin_unlock_irq(&cq->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mthca_resize_cq(struct ib_cq *ibcq, int entries, struct ib_udata *udata)
|
||||
{
|
||||
struct mthca_dev *dev = to_mdev(ibcq->device);
|
||||
struct mthca_cq *cq = to_mcq(ibcq);
|
||||
struct mthca_resize_cq ucmd;
|
||||
u32 lkey;
|
||||
u8 status;
|
||||
int ret;
|
||||
|
||||
if (entries < 1 || entries > dev->limits.max_cqes)
|
||||
return -EINVAL;
|
||||
|
||||
entries = roundup_pow_of_two(entries + 1);
|
||||
if (entries == ibcq->cqe + 1)
|
||||
return 0;
|
||||
|
||||
if (cq->is_kernel) {
|
||||
ret = mthca_alloc_resize_buf(dev, cq, entries);
|
||||
if (ret)
|
||||
return ret;
|
||||
lkey = cq->resize_buf->buf.mr.ibmr.lkey;
|
||||
} else {
|
||||
if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd))
|
||||
return -EFAULT;
|
||||
lkey = ucmd.lkey;
|
||||
}
|
||||
|
||||
ret = mthca_RESIZE_CQ(dev, cq->cqn, lkey, long_log2(entries), &status);
|
||||
if (status)
|
||||
ret = -EINVAL;
|
||||
|
||||
if (ret) {
|
||||
if (cq->resize_buf) {
|
||||
mthca_free_cq_buf(dev, &cq->resize_buf->buf,
|
||||
cq->resize_buf->cqe);
|
||||
kfree(cq->resize_buf);
|
||||
spin_lock_irq(&cq->lock);
|
||||
cq->resize_buf = NULL;
|
||||
spin_unlock_irq(&cq->lock);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (cq->is_kernel) {
|
||||
struct mthca_cq_buf tbuf;
|
||||
int tcqe;
|
||||
|
||||
spin_lock_irq(&cq->lock);
|
||||
if (cq->resize_buf->state == CQ_RESIZE_READY) {
|
||||
mthca_cq_resize_copy_cqes(cq);
|
||||
tbuf = cq->buf;
|
||||
tcqe = cq->ibcq.cqe;
|
||||
cq->buf = cq->resize_buf->buf;
|
||||
cq->ibcq.cqe = cq->resize_buf->cqe;
|
||||
} else {
|
||||
tbuf = cq->resize_buf->buf;
|
||||
tcqe = cq->resize_buf->cqe;
|
||||
}
|
||||
|
||||
kfree(cq->resize_buf);
|
||||
cq->resize_buf = NULL;
|
||||
spin_unlock_irq(&cq->lock);
|
||||
|
||||
mthca_free_cq_buf(dev, &tbuf, tcqe);
|
||||
} else
|
||||
ibcq->cqe = entries - 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mthca_destroy_cq(struct ib_cq *cq)
|
||||
{
|
||||
if (cq->uobject) {
|
||||
@@ -1113,6 +1230,7 @@ int mthca_register_device(struct mthca_dev *dev)
|
||||
(1ull << IB_USER_VERBS_CMD_DEREG_MR) |
|
||||
(1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) |
|
||||
(1ull << IB_USER_VERBS_CMD_CREATE_CQ) |
|
||||
(1ull << IB_USER_VERBS_CMD_RESIZE_CQ) |
|
||||
(1ull << IB_USER_VERBS_CMD_DESTROY_CQ) |
|
||||
(1ull << IB_USER_VERBS_CMD_CREATE_QP) |
|
||||
(1ull << IB_USER_VERBS_CMD_MODIFY_QP) |
|
||||
@@ -1154,6 +1272,7 @@ int mthca_register_device(struct mthca_dev *dev)
|
||||
dev->ib_dev.modify_qp = mthca_modify_qp;
|
||||
dev->ib_dev.destroy_qp = mthca_destroy_qp;
|
||||
dev->ib_dev.create_cq = mthca_create_cq;
|
||||
dev->ib_dev.resize_cq = mthca_resize_cq;
|
||||
dev->ib_dev.destroy_cq = mthca_destroy_cq;
|
||||
dev->ib_dev.poll_cq = mthca_poll_cq;
|
||||
dev->ib_dev.get_dma_mr = mthca_get_dma_mr;
|
||||
|
Reference in New Issue
Block a user