-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;
-}
-